// Copyright (c) 2019, 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.

import 'package:async/async.dart';
import 'package:dwds/src/config/tool_configuration.dart';
import 'package:dwds/src/debugging/modules.dart';
import 'package:dwds/src/readers/asset_reader.dart';
import 'package:dwds/src/utilities/dart_uri.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as p;
import 'package:source_maps/parser.dart';
import 'package:source_maps/source_maps.dart';

var _startTokenId = 1337;

/// A source location, with both Dart and JS information.
class Location {
  final JsLocation jsLocation;

  final DartLocation dartLocation;

  /// An arbitrary integer value used to represent this location.
  final int tokenPos;

  Location._(
    this.jsLocation,
    this.dartLocation,
  ) : tokenPos = _startTokenId++;

  static Location from(
    String module,
    TargetLineEntry lineEntry,
    TargetEntry entry,
    DartUri dartUri,
  ) {
    final dartLine = entry.sourceLine;
    final dartColumn = entry.sourceColumn;
    final jsLine = lineEntry.line;
    final jsColumn = entry.column;

    // lineEntry data is 0 based according to:
    // https://docs.google.com/document/d/1U1RGAehQwRypUTovF1KRlpiOFze0b-_2gc6fAH0KY0k
    return Location._(
      JsLocation.fromZeroBased(module, jsLine, jsColumn),
      DartLocation.fromZeroBased(dartUri, dartLine ?? 0, dartColumn ?? 0),
    );
  }

  @override
  String toString() => '$dartLocation -> $jsLocation';
}

/// Location information for a Dart source.
class DartLocation {
  final DartUri uri;

  /// 1 based row offset within the Dart source code.
  final int line;

  /// 1 based column offset within the Dart source code.
  final int column;

  DartLocation._(
    this.uri,
    this.line,
    this.column,
  );

  int compareTo(DartLocation other) => compareToLine(other.line, other.column);

  int compareToLine(int otherLine, int otherColumn) {
    final result = line.compareTo(otherLine);
    return result == 0 ? column.compareTo(otherColumn) : result;
  }

  @override
  int get hashCode => Object.hashAll([uri, line, column]);

  @override
  bool operator ==(Object other) {
    if (other is! DartLocation) {
      return false;
    }
    return uri.serverPath == other.uri.serverPath &&
        line == other.line &&
        column == other.column;
  }

  @override
  String toString() => '[${uri.serverPath}:$line:$column]';

  factory DartLocation.fromZeroBased(DartUri uri, int line, int column) =>
      DartLocation._(uri, line + 1, column + 1);
}

/// Location information for a JS source.
class JsLocation {
  final String module;

  /// 0 based row offset within the JS source code.
  final int line;

  /// 0 based column offset within the JS source code.
  final int column;

  JsLocation._(
    this.module,
    this.line,
    this.column,
  );

  int compareTo(JsLocation other) => compareToLine(other.line, other.column);

  int compareToLine(int otherLine, int otherColumn) {
    final result = line.compareTo(otherLine);
    return result == 0 ? column.compareTo(otherColumn) : result;
  }

  @override
  String toString() => '[$module:$line:$column]';

  // JS Location is 0 based according to:
  // https://chromedevtools.github.io/devtools-protocol/tot/Debugger#type-Location
  factory JsLocation.fromZeroBased(String module, int line, int column) =>
      JsLocation._(module, line, column);
}

/// Contains meta data for known [Location]s.
class Locations {
  final _logger = Logger('Locations');

  /// [Location] data for Dart server path.
  final Map<String, Set<Location>> _sourceToLocation = {};
  final Map<String, AsyncMemoizer<Set<Location>>> _locationMemoizer = {};

  /// `tokenPosTable` for Dart server path, as defined in the
  /// Dart VM Service Protocol:
  /// https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md#script
  final Map<String, List<List<int>>> _sourceToTokenPosTable = {};

  /// The set of all known [Location]s for a module.
  final Map<String, Set<Location>> _moduleToLocations = {};

  final AssetReader _assetReader;
  final Modules _modules;
  final String _root;

  late String _entrypoint;

  Locations(this._assetReader, this._modules, this._root);

  Modules get modules => _modules;

  void initialize(String entrypoint) {
    _sourceToTokenPosTable.clear();
    _sourceToLocation.clear();
    _locationMemoizer.clear();
    _moduleToLocations.clear();
    _entrypoint = entrypoint;
  }

  /// Returns all [Location] data for a provided Dart source.
  Future<Set<Location>> locationsForDart(String serverPath) async {
    final module = await _modules.moduleForSource(serverPath);
    if (module == null) {
      _logger.warning('No module for server path $serverPath');
    } else {
      await _locationsForModule(module);
    }
    return _sourceToLocation[serverPath] ?? {};
  }

  /// Returns all [Location] data for a provided JS server path.
  Future<Set<Location>> locationsForUrl(String url) async {
    if (url.isEmpty) return {};

    final dartUri = DartUri(url, _root);
    final serverPath = dartUri.serverPath;
    final module = await globalToolConfiguration.loadStrategy
        .moduleForServerPath(_entrypoint, serverPath);

    final cache = _moduleToLocations[module];
    if (cache != null) return cache;
    if (module != null) {
      await _locationsForModule(module);
    }
    return _moduleToLocations[module] ?? {};
  }

  /// Find the [Location] for the given Dart source position.
  ///
  /// The [line] number is 1-based.
  Future<Location?> locationForDart(DartUri uri, int line, int column) async {
    final locations = await locationsForDart(uri.serverPath);
    return _bestDartLocation(locations, line, column);
  }

  /// Find the [Location] for the given JS source position.
  ///
  /// The [line] number is 0-based.
  Future<Location?> locationForJs(String url, int line, int? column) async {
    final locations = await locationsForUrl(url);
    return _bestJsLocation(locations, line, column);
  }

  /// Find closest existing Dart location for the line and column.
  ///
  /// Dart columns for breakpoints are either exact or start at the
  /// beginning of the line - return the first existing location
  /// that comes after the given column.
  Location? _bestDartLocation(
    Iterable<Location> locations,
    int line,
    int column,
  ) {
    Location? bestLocation;
    for (var location in locations) {
      if (location.dartLocation.line == line &&
          location.dartLocation.column >= column) {
        bestLocation ??= location;
        if (location.dartLocation.compareTo(bestLocation.dartLocation) < 0) {
          bestLocation = location;
        }
      }
    }
    return bestLocation;
  }

  /// Find closest existing JavaScript location for the line and column.
  ///
  /// Some JS locations are not stored in the source maps, so we find the
  /// closest existing location coming before the given column.
  ///
  /// This is a known problem that other code bases solve using by finding
  /// the closest location to the current one:
  ///
  /// https://github.com/microsoft/vscode-js-debug/blob/536f96bae61a3d87546b61bc7916097904c81429/src/common/sourceUtils.ts#L286
  Location? _bestJsLocation(
    Iterable<Location> locations,
    int line,
    int? column,
  ) {
    column ??= 0;
    Location? bestLocation;
    for (var location in locations) {
      if (location.jsLocation.compareToLine(line, column) <= 0) {
        bestLocation ??= location;
        if (location.jsLocation.compareTo(bestLocation.jsLocation) > 0) {
          bestLocation = location;
        }
      }
    }
    return bestLocation;
  }

  /// Returns the tokenPosTable for the provided Dart script path as defined
  /// in:
  /// https://github.com/dart-lang/sdk/blob/main/runtime/vm/service/service.md#script
  Future<List<List<int>>> tokenPosTableFor(String serverPath) async {
    var tokenPosTable = _sourceToTokenPosTable[serverPath];
    if (tokenPosTable != null) return tokenPosTable;
    // Construct the tokenPosTable which is of the form:
    // [lineNumber, (tokenId, columnNumber)*]
    tokenPosTable = <List<int>>[];
    final locations = await locationsForDart(serverPath);
    final lineNumberToLocation = <int, Set<Location>>{};
    for (var location in locations) {
      lineNumberToLocation
          .putIfAbsent(location.dartLocation.line, () => <Location>{})
          .add(location);
    }
    for (var lineNumber in lineNumberToLocation.keys) {
      final locations = lineNumberToLocation[lineNumber]!;
      tokenPosTable.add([
        lineNumber,
        for (var location in locations) ...[
          location.tokenPos,
          location.dartLocation.column,
        ],
      ]);
    }
    _sourceToTokenPosTable[serverPath] = tokenPosTable;
    return tokenPosTable;
  }

  /// Returns all known [Location]s for the provided [module].
  ///
  /// [module] refers to the JS path of a DDC module without the extension.
  ///
  /// This will populate the [_sourceToLocation] and [_moduleToLocations] maps.
  Future<Set<Location>> _locationsForModule(String module) {
    final memoizer = _locationMemoizer.putIfAbsent(module, AsyncMemoizer.new);

    return memoizer.runOnce(() async {
      if (_moduleToLocations.containsKey(module)) {
        return _moduleToLocations[module]!;
      }
      final result = <Location>{};
      if (module.isEmpty) return _moduleToLocations[module] = result;
      if (module.endsWith('dart_sdk') ||
          (module.endsWith('dart_library') &&
              !module.endsWith('.dart_library'))) {
        return result;
      }
      final modulePath = await globalToolConfiguration.loadStrategy
          .serverPathForModule(_entrypoint, module);
      if (modulePath == null) {
        _logger.warning('No module path for module: $module');
        return result;
      }
      final sourceMapPath = await globalToolConfiguration.loadStrategy
          .sourceMapPathForModule(_entrypoint, module);
      if (sourceMapPath == null) {
        _logger.warning('No sourceMap path for module: $module');
        return result;
      }
      final sourceMapContents =
          await _assetReader.sourceMapContents(sourceMapPath);
      final scriptLocation =
          p.url.dirname('/${stripLeadingSlashes(modulePath)}');

      if (sourceMapContents == null) return result;
      // This happens to be a [SingleMapping] today in DDC.
      final mapping = parse(sourceMapContents);
      if (mapping is SingleMapping) {
        // Create TokenPos for each entry in the source map.
        for (var lineEntry in mapping.lines) {
          for (var entry in lineEntry.entries) {
            final index = entry.sourceUrlId;
            if (index == null) continue;
            // Source map URLS are relative to the script. They may have platform separators
            // or they may use URL semantics. To be sure, we split and re-join them.
            // This works on Windows because path treats both / and \ as separators.
            // It will fail if the path has both separators in it.
            final relativeSegments = p.split(mapping.urls[index]);
            final path = p.url.normalize(
              p.url.joinAll([scriptLocation, ...relativeSegments]),
            );

            final dartUri = DartUri(path, _root);
            result.add(
              Location.from(
                modulePath,
                lineEntry,
                entry,
                dartUri,
              ),
            );
          }
        }
      }
      for (var location in result) {
        _sourceToLocation
            .putIfAbsent(
              location.dartLocation.uri.serverPath,
              () => <Location>{},
            )
            .add(location);
      }
      return _moduleToLocations[module] = result;
    });
  }
}
