// 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.
library;

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

import 'package:source_maps/source_maps.dart';
// ignore: implementation_imports
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 = {};
  late final List<int> frameIndex = frames.keys.toList()..sort();

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

  Dart2jsMapping.json(Map json) : this(parseSingleMapping(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;

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

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

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

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.
  @override
  bool moveNext() => ++index < _length;

  @override
  String get current =>
      (index >= 0 && index < _length)
          ? _internal[index]
          : throw StateError('No current value available.');

  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(FrameEntry.pop(true));
        index++;
        continue;
      } else if (marker == ',') {
        entries.add(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(FrameEntry.push(uri, line, column, name));
      }
    }
  }
}

void _extractMinifiedNames(
  String encodedInput,
  SingleMapping sourceMap,
  Map<String, String> minifiedNames,
  Logger? logger,
) {
  if (encodedInput.isEmpty) return;
  List<String> input = encodedInput.split(',');
  if (input.length % 2 != 0) {
    logger?.log("Error: expected an even number of entries");
  }
  for (int i = 0; i < input.length; i += 2) {
    String minifiedName = input[i];
    int id = int.parse(input[i + 1]);
    minifiedNames[minifiedName] = sourceMap.names[id];
  }
}
