// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.

/// Representation of a source-map file with dart2js-specific extensions, and
/// helper functions to parse them.

import 'dart:convert';
import 'dart:io';

import 'package:source_maps/source_maps.dart';
import 'package:source_maps/src/vlq.dart';

import 'util.dart';

/// Representation of a source-map file with dart2js-specific extensions.
///
/// Dart2js adds a special section that provides: tables of minified names and a
/// table of inlining frame data.
class Dart2jsMapping {
  final SingleMapping sourceMap;

  final Map<String, String> globalNames = {};
  final Map<String, String> instanceNames = {};
  final Map<int, List<FrameEntry>> frames = {};
  List<int> _frameIndex;
  List<int> get frameIndex {
    if (_frameIndex == null) {
      _frameIndex = frames.keys.toList()..sort();
    }
    return _frameIndex;
  }

  Dart2jsMapping(this.sourceMap, Map json) {
    var extensions = json['x_org_dartlang_dart2js'];
    if (extensions == null) return;
    var minifiedNames = extensions['minified_names'];
    if (minifiedNames != null) {
      _extractMinifedNames(minifiedNames['global'], sourceMap, globalNames);
      _extractMinifedNames(minifiedNames['instance'], sourceMap, instanceNames);
    }
    String jsonFrames = extensions['frames'];
    if (jsonFrames != null) {
      new _FrameDecoder(jsonFrames).parseFrames(frames, sourceMap);
    }
  }

  Dart2jsMapping.json(Map json) : this(parseJson(json), json);
}

class FrameEntry {
  final String callUri;
  final int callLine;
  final int callColumn;
  final String inlinedMethodName;
  final bool isEmpty;
  FrameEntry.push(
      this.callUri, this.callLine, this.callColumn, this.inlinedMethodName)
      : isEmpty = false;
  FrameEntry.pop(this.isEmpty)
      : callUri = null,
        callLine = null,
        callColumn = null,
        inlinedMethodName = null;

  bool get isPush => callUri != null;
  bool get isPop => callUri == null;

  toString() {
    if (isPush)
      return "push $inlinedMethodName @ $callUri:$callLine:$callColumn";
    return isEmpty ? 'pop: empty' : 'pop';
  }
}

const _marker = "\n//# sourceMappingURL=";
Dart2jsMapping parseMappingFor(Uri uri) {
  var file = new File.fromUri(uri);
  if (!file.existsSync()) {
    warn('Error: no such file: $uri');
    return null;
  }
  var contents = file.readAsStringSync();
  var urlIndex = contents.indexOf(_marker);
  var sourcemapPath;
  if (urlIndex != -1) {
    sourcemapPath = contents.substring(urlIndex + _marker.length).trim();
  } else {
    warn('Error: source-map url marker not found in $uri\n'
        '       trying $uri.map');
    sourcemapPath = '${uri.pathSegments.last}.map';
  }

  assert(!sourcemapPath.contains('\n'));
  var sourcemapFile = new File.fromUri(uri.resolve(sourcemapPath));
  if (!sourcemapFile.existsSync()) {
    warn('Error: no such file: $sourcemapFile');
    return null;
  }
  var json = jsonDecode(sourcemapFile.readAsStringSync());
  return new Dart2jsMapping(parseJson(json), json);
}

class _FrameDecoder implements Iterator<String> {
  final String _internal;
  final int _length;
  int index = -1;
  _FrameDecoder(this._internal) : _length = _internal.length;

  // Iterator API is used by decodeVlq to consume VLQ entries.
  bool moveNext() => ++index < _length;

  String get current =>
      (index >= 0 && index < _length) ? _internal[index] : null;

  bool get hasTokens => index < _length - 1 && _length > 0;

  int _readDelta() => decodeVlq(this);

  void parseFrames(Map<int, List<FrameEntry>> frames, SingleMapping sourceMap) {
    var offset = 0;
    var uriId = 0;
    var nameId = 0;
    var line = 0;
    var column = 0;
    while (hasTokens) {
      offset += _readDelta();
      List<FrameEntry> entries = frames[offset] ??= [];
      var marker = _internal[index + 1];
      if (marker == ';') {
        entries.add(new FrameEntry.pop(true));
        index++;
        continue;
      } else if (marker == ',') {
        entries.add(new FrameEntry.pop(false));
        index++;
        continue;
      } else {
        uriId += _readDelta();
        var uri = sourceMap.urls[uriId];
        line += _readDelta();
        column += _readDelta();
        nameId += _readDelta();
        var name = sourceMap.names[nameId];
        entries.add(new FrameEntry.push(uri, line, column, name));
      }
    }
  }
}

_extractMinifedNames(String encodedInput, SingleMapping sourceMap,
    Map<String, String> minifiedNames) {
  List<String> input = encodedInput.split(',');
  if (input.length % 2 != 0) {
    warn("expected an even number of entries");
  }
  for (int i = 0; i < input.length; i += 2) {
    String minifiedName = input[i];
    int id = int.tryParse(input[i + 1]);
    minifiedNames[minifiedName] = sourceMap.names[id];
  }
}
