// 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/metadata/provider.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,
    String? runtimeScriptId,
  ) {
    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, runtimeScriptId),
      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;

  /// The Runtime.ScriptId of a script in Chrome.
  ///
  /// See https://chromedevtools.github.io/devtools-protocol/tot/Runtime/#type-ScriptId
  String? runtimeScriptId;

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

  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,
    String? runtimeScriptId,
  ) => JsLocation._(module, line, column, runtimeScriptId);
}

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

  /// Initialize any caches.
  ///
  /// If [modifiedModuleReport] is not null, only invalidates the caches for the
  /// modified modules instead.
  Future<void> initialize(
    String entrypoint, {
    ModifiedModuleReport? modifiedModuleReport,
  }) async {
    // If we know that only certain modules are deleted or added, we can only
    // invalidate those.
    if (modifiedModuleReport != null) {
      for (final module in modifiedModuleReport.modifiedModules) {
        _locationMemoizer.remove(module);
        _moduleToLocations.remove(module);
        final sources = await _modules.sourcesForModule(module);
        if (sources != null) {
          for (final serverPath in sources) {
            _sourceToTokenPosTable.remove(serverPath);
            _sourceToLocation.remove(serverPath);
          }
        }
      }
      return;
    }
    _locationMemoizer.clear();
    _moduleToLocations.clear();
    _sourceToTokenPosTable.clear();
    _sourceToLocation.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 (final 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 (final 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 (final location in locations) {
      lineNumberToLocation
          .putIfAbsent(location.dartLocation.line, () => <Location>{})
          .add(location);
    }
    for (final lineNumber in lineNumberToLocation.keys) {
      final locations = lineNumberToLocation[lineNumber]!;
      tokenPosTable.add([
        lineNumber,
        for (final 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;

      final runtimeScriptId = await _modules.getRuntimeScriptIdForModule(
        _entrypoint,
        module,
      );

      // 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 (final lineEntry in mapping.lines) {
          for (final entry in lineEntry.entries) {
            final location = _locationForSourceMapEntry(
              lineEntry: lineEntry,
              entry: entry,
              modulePath: modulePath,
              runtimeScriptId: runtimeScriptId,
              sourceUrls: mapping.urls,
              scriptLocation: scriptLocation,
            );
            if (location != null) {
              result.add(location);
            }
          }
        }
      }
      for (final location in result) {
        _sourceToLocation
            .putIfAbsent(
              location.dartLocation.uri.serverPath,
              () => <Location>{},
            )
            .add(location);
      }
      return _moduleToLocations[module] = result;
    });
  }

  /// Creates a TokenPos [Location] for an entry in the source map.
  Location? _locationForSourceMapEntry({
    required TargetLineEntry lineEntry,
    required TargetEntry entry,
    required String modulePath,
    required String? runtimeScriptId,
    required List<String> sourceUrls,
    required String scriptLocation,
  }) {
    final index = entry.sourceUrlId;
    if (index == null) return null;
    // 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(sourceUrls[index]);
    final path = p.url.normalize(
      p.url.joinAll([scriptLocation, ...relativeSegments]),
    );

    try {
      final dartUri = DartUri(path, _root);
      return Location.from(
        modulePath,
        lineEntry,
        entry,
        dartUri,
        runtimeScriptId,
      );
    } catch (error) {
      // DartUri throws if the path format is unrecognized. Log any errors and
      // return null in that case.
      _logger.warning('Error adding location for $path: $error');
      return null;
    }
  }
}
