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

library sourcemap.helper;

import 'dart:async';
import 'dart:io';
import 'package:compiler/compiler_api.dart' as api;
import 'package:compiler/src/commandline_options.dart';
import 'package:compiler/src/compiler.dart' show Compiler;
import 'package:compiler/src/elements/entities.dart';
import 'package:compiler/src/io/code_output.dart';
import 'package:compiler/src/io/source_file.dart';
import 'package:compiler/src/io/source_information.dart';
import 'package:compiler/src/io/position_information.dart';
import 'package:compiler/src/js/js.dart' as js;
import 'package:compiler/src/js/js_debug.dart';
import 'package:compiler/src/js/js_source_mapping.dart';
import 'package:compiler/src/js_model/element_map.dart';
import 'package:compiler/src/js_model/js_strategy.dart';
import 'package:compiler/src/source_file_provider.dart';
import 'package:compiler/src/util/memory_compiler.dart';

class SourceFileSink implements api.OutputSink {
  final String filename;
  StringBuffer sb = StringBuffer();
  late final SourceFile sourceFile;

  SourceFileSink(this.filename);

  @override
  void add(String event) {
    sb.write(event);
  }

  @override
  void close() {
    sourceFile = StringSourceFile.fromName(filename, sb.toString());
  }
}

class OutputProvider implements api.CompilerOutput {
  Map<Uri, SourceFileSink> outputMap = <Uri, SourceFileSink>{};

  SourceFile? getSourceFile(Uri uri) {
    SourceFileSink? sink = outputMap[uri];
    return sink?.sourceFile;
  }

  SourceFileSink createSourceFileSink(
    String name,
    String extension,
    api.OutputType type,
  ) {
    String filename = '$name.$extension';
    SourceFileSink sink = SourceFileSink(filename);
    Uri uri = Uri.parse(filename);
    outputMap[uri] = sink;
    return sink;
  }

  @override
  api.OutputSink createOutputSink(
    String name,
    String extension,
    api.OutputType type,
  ) {
    return createSourceFileSink(name, extension, type);
  }

  @override
  api.BinaryOutputSink createBinarySink(Uri uri) =>
      throw UnsupportedError("OutputProvider.createBinarySink");
}

class CloningOutputProvider extends OutputProvider {
  RandomAccessFileOutputProvider outputProvider;

  CloningOutputProvider(Uri jsUri, Uri jsMapUri)
    : outputProvider = RandomAccessFileOutputProvider(
        jsUri,
        jsMapUri,
        onInfo: _ignore,
        onFailure: _fail,
      );

  static void _ignore(String message) {}

  static Never _fail(String message) => throw StateError('unreachable');

  @override
  api.OutputSink createOutputSink(
    String name,
    String extension,
    api.OutputType type,
  ) {
    api.OutputSink output = outputProvider.createOutputSink(
      name,
      extension,
      type,
    );
    return CloningOutputSink([
      output,
      createSourceFileSink(name, extension, type),
    ]);
  }

  @override
  api.BinaryOutputSink createBinarySink(Uri uri) =>
      throw UnsupportedError("CloningOutputProvider.createBinarySink");
}

abstract class SourceFileManager {
  SourceFile? getSourceFile(Object? uri);
}

class ProviderSourceFileManager implements SourceFileManager {
  final SourceFileProvider sourceFileProvider;
  final OutputProvider outputProvider;

  ProviderSourceFileManager(this.sourceFileProvider, this.outputProvider);

  @override
  SourceFile? getSourceFile(covariant Uri? uri) {
    if (uri == null) return null;
    return (sourceFileProvider.readUtf8FromFileSyncForTesting(uri) ??
            outputProvider.getSourceFile(uri))
        as SourceFile?;
  }
}

class RecordingPrintingContext extends LenientPrintingContext {
  CodePositionListener listener;
  Map<js.Node, CodePosition> codePositions = <js.Node, CodePosition>{};

  RecordingPrintingContext(this.listener);

  @override
  void exitNode(
    js.Node node,
    int startPosition,
    int endPosition,
    int? closingPosition,
  ) {
    codePositions[node] = CodePosition(
      startPosition,
      endPosition,
      closingPosition,
    );
    listener.onPositions(node, startPosition, endPosition, closingPosition);
  }
}

/// A [SourceMapper] that records the source locations on each node.
class RecordingSourceMapperProvider implements SourceMapperProvider {
  final SourceMapperProvider sourceMapperProvider;
  final _LocationRecorder nodeToSourceLocationsMap;

  RecordingSourceMapperProvider(
    this.sourceMapperProvider,
    this.nodeToSourceLocationsMap,
  );

  @override
  SourceMapper createSourceMapper(String name) {
    return RecordingSourceMapper(
      sourceMapperProvider.createSourceMapper(name),
      nodeToSourceLocationsMap,
    );
  }
}

/// A [SourceMapper] that records the source locations on each node.
class RecordingSourceMapper implements SourceMapper {
  final SourceMapper sourceMapper;
  final _LocationRecorder nodeToSourceLocationsMap;

  RecordingSourceMapper(this.sourceMapper, this.nodeToSourceLocationsMap);

  @override
  void register(js.Node node, int codeOffset, SourceLocation sourceLocation) {
    nodeToSourceLocationsMap.register(node, codeOffset, sourceLocation);
    sourceMapper.register(node, codeOffset, sourceLocation);
  }

  @override
  void registerPush(
    int codeOffset,
    SourceLocation? sourceLocation,
    String inlinedMethodName,
  ) {
    sourceMapper.registerPush(codeOffset, sourceLocation, inlinedMethodName);
  }

  @override
  void registerPop(int codeOffset, {bool isEmpty = false}) {
    sourceMapper.registerPop(codeOffset, isEmpty: isEmpty);
  }
}

/// A wrapper of [SourceInformationProcessor] that records source locations and
/// code positions.
class RecordingSourceInformationProcessor extends SourceInformationProcessor {
  final RecordingSourceInformationStrategy wrapper;
  final SourceInformationProcessor processor;
  final CodePositionRecorder codePositions;
  final LocationMap nodeToSourceLocationsMap;

  RecordingSourceInformationProcessor(
    this.wrapper,
    this.processor,
    this.codePositions,
    this.nodeToSourceLocationsMap,
  );

  @override
  void onStartPosition(js.Node node, int startPosition) {
    processor.onStartPosition(node, startPosition);
  }

  @override
  void onPositions(
    js.Node node,
    int startPosition,
    int endPosition,
    int? closingPosition,
  ) {
    codePositions.registerPositions(
      node,
      startPosition,
      endPosition,
      closingPosition,
    );
    processor.onPositions(node, startPosition, endPosition, closingPosition);
  }

  @override
  void process(js.Node node, BufferedCodeOutput code) {
    processor.process(node, code);
    wrapper.registerProcess(
      node,
      code,
      codePositions,
      nodeToSourceLocationsMap,
    );
  }
}

/// Information recording for a use of [SourceInformationProcessor].
class RecordedSourceInformationProcess {
  final js.Node root;
  final String code;
  final CodePositionRecorder codePositions;
  final LocationMap nodeToSourceLocationsMap;

  RecordedSourceInformationProcess(
    this.root,
    this.code,
    this.codePositions,
    this.nodeToSourceLocationsMap,
  );
}

/// A wrapper of [JavaScriptSourceInformationStrategy] that records
/// [RecordedSourceInformationProcess].
class RecordingSourceInformationStrategy
    extends JavaScriptSourceInformationStrategy {
  final JavaScriptSourceInformationStrategy strategy;
  final Map<RecordedSourceInformationProcess, js.Node> processMap =
      <RecordedSourceInformationProcess, js.Node>{};
  final Map<js.Node, RecordedSourceInformationProcess?> nodeMap = {};

  RecordingSourceInformationStrategy(this.strategy);

  @override
  void onElementMapAvailable(JsToElementMap elementMap) {
    strategy.onElementMapAvailable(elementMap);
  }

  @override
  SourceInformationBuilder createBuilderForContext(MemberEntity member) {
    return strategy.createBuilderForContext(member);
  }

  @override
  SourceInformationProcessor createProcessor(
    SourceMapperProvider provider,
    SourceInformationReader reader,
  ) {
    final nodeToSourceLocationsMap = _LocationRecorder();
    final codePositions = CodePositionRecorder();
    return RecordingSourceInformationProcessor(
      this,
      strategy.createProcessor(
        RecordingSourceMapperProvider(provider, nodeToSourceLocationsMap),
        reader,
      ),
      codePositions,
      nodeToSourceLocationsMap,
    );
  }

  void registerProcess(
    js.Node root,
    BufferedCodeOutput code,
    CodePositionRecorder codePositions,
    LocationMap nodeToSourceLocationsMap,
  ) {
    RecordedSourceInformationProcess subProcess =
        RecordedSourceInformationProcess(
          root,
          code.getText(),
          codePositions,
          nodeToSourceLocationsMap,
        );
    processMap[subProcess] = root;
  }

  RecordedSourceInformationProcess? subProcessForNode(js.Node node) {
    return nodeMap.putIfAbsent(node, () {
      for (RecordedSourceInformationProcess subProcess in processMap.keys) {
        js.Node root = processMap[subProcess]!;
        FindVisitor visitor = FindVisitor(node);
        root.accept(visitor);
        if (visitor.found) {
          return RecordedSourceInformationProcess(
            node,
            subProcess.code,
            subProcess.codePositions,
            _FilteredLocationMap(
              visitor.nodes,
              subProcess.nodeToSourceLocationsMap,
            ),
          );
        }
        return null;
      }
      return null;
    });
  }
}

/// Visitor that collects all nodes that are within a function. Used by the
/// [RecordingSourceInformationStrategy] to filter what is recorded in a
/// [RecordedSourceInformationProcess].
class FindVisitor extends js.BaseVisitorVoid {
  final js.Node soughtNode;
  bool found = false;
  bool add = false;
  final Set<js.Node> nodes = Set<js.Node>();

  FindVisitor(this.soughtNode);

  @override
  void visitNode(js.Node node) {
    if (node == soughtNode) {
      found = true;
      add = true;
    }
    if (add) {
      nodes.add(node);
    }
    node.visitChildren(this);
    if (node == soughtNode) {
      add = false;
    }
  }
}

class HelperOnlinePositionSourceInformationStrategy
    implements JavaScriptSourceInformationStrategy {
  final List<TraceListener> listeners;
  HelperOnlinePositionSourceInformationStrategy(this.listeners);

  @override
  SourceInformationProcessor createProcessor(
    SourceMapperProvider provider,
    SourceInformationReader reader,
  ) {
    return OnlineSourceInformationProcessor(provider, reader, listeners);
  }

  @override
  void onComplete() {}

  @override
  SourceInformation buildSourceMappedMarker() {
    return const SourceMappedMarker();
  }

  @override
  SourceInformationBuilder createBuilderForContext(
    covariant MemberEntity member,
  ) {
    throw UnimplementedError();
  }

  @override
  void onElementMapAvailable(JsToElementMap elementMap) {}
}

/// Processor that computes [SourceMapInfo] for the JavaScript compiled for a
/// given Dart file.
class SourceMapProcessor {
  /// If `true` the output from the compilation is written to files.
  final bool outputToFile;

  /// The [Uri] of the Dart entrypoint.
  Uri inputUri;

  /// The name of the JavaScript output file.
  String jsPath;

  /// The [Uri] of the JavaScript output file.
  Uri targetUri;

  /// The [Uri] of the JavaScript source map file.
  Uri sourceMapFileUri;

  /// The [SourceFileManager] created for the processing.
  late final SourceFileManager sourceFileManager;

  /// Creates a processor for the Dart file [uri].
  SourceMapProcessor(Uri uri, {this.outputToFile = false})
    : inputUri = Uri.base.resolveUri(uri),
      jsPath = 'out.js',
      targetUri = Uri.base.resolve('out.js'),
      sourceMapFileUri = Uri.base.resolve('out.js.map');

  /// Computes the [SourceMapInfo] for the compiled elements.
  Future<SourceMaps> process(
    List<String> options, {
    bool verbose = true,
    bool perElement = true,
    bool forMain = false,
  }) async {
    OutputProvider outputProvider =
        outputToFile
            ? CloningOutputProvider(targetUri, sourceMapFileUri)
            : OutputProvider();
    if (options.contains(Flags.useNewSourceInfo)) {
      if (verbose) print('Using the source information system.');
    }
    if (options.contains(Flags.disableInlining)) {
      if (verbose) print('Inlining disabled');
    }
    CompilationResult result = await runCompiler(
      entryPoint: inputUri,
      outputProvider: outputProvider,
      // TODO(johnniwinther): Use [verbose] to avoid showing diagnostics.
      options: ['--out=$targetUri', '--source-map=$sourceMapFileUri']
        ..addAll(options),
      beforeRun: (compiler) {
        JsBackendStrategy backendStrategy = compiler.backendStrategy;
        dynamic handler = compiler.handler;
        SourceFileProvider sourceFileProvider = handler.provider;
        sourceFileManager = ProviderSourceFileManager(
          sourceFileProvider,
          outputProvider,
        );
        RecordingSourceInformationStrategy strategy =
            RecordingSourceInformationStrategy(
              backendStrategy.sourceInformationStrategy
                  as JavaScriptSourceInformationStrategy,
            );
        backendStrategy.sourceInformationStrategy = strategy;
      },
    );
    if (!result.isSuccess) {
      throw "Compilation failed.";
    }

    var compiler = result.compiler!;
    JsBackendStrategy backendStrategy = compiler.backendStrategy;
    final strategy =
        backendStrategy.sourceInformationStrategy
            as RecordingSourceInformationStrategy;
    SourceMapInfo? mainSourceMapInfo;
    Map<MemberEntity, SourceMapInfo> elementSourceMapInfos =
        <MemberEntity, SourceMapInfo>{};
    if (perElement) {
      backendStrategy.generatedCode.forEach((_element, js.Expression node) {
        MemberEntity element = _element;
        RecordedSourceInformationProcess? subProcess = strategy
            .subProcessForNode(node);
        if (subProcess == null) {
          // TODO(johnniwinther): Find out when this is happening and if it
          // is benign. (Known to happen for `bool#fromString`)
          print('No subProcess found for $element');
          return;
        }
        LocationMap nodeMap = subProcess.nodeToSourceLocationsMap;
        String code = subProcess.code;
        CodePositionRecorder codePositions = subProcess.codePositions;
        CodePointComputer visitor = CodePointComputer(
          sourceFileManager,
          code,
          nodeMap,
        );
        final outBuffer = NoopCodeOutput();
        SourceInformationProcessor sourceInformationProcessor =
            HelperOnlinePositionSourceInformationStrategy([
              visitor,
            ]).createProcessor(
              SourceMapperProviderImpl(outBuffer),
              const SourceInformationReader(),
            );

        js.Dart2JSJavaScriptPrintingContext context =
            js.Dart2JSJavaScriptPrintingContext(
              null,
              outBuffer,
              sourceInformationProcessor,
              const js.JavaScriptAnnotationMonitor(),
            );
        js.Printer printer = js.Printer(
          const js.JavaScriptPrintingOptions(),
          context,
        );
        printer.visit(node);
        List<CodePoint> codePoints = visitor.codePoints;
        elementSourceMapInfos[element] = SourceMapInfo(
          element,
          code,
          node,
          codePoints,
          codePositions,
          nodeMap,
        );
      });
    }
    if (forMain) {
      // TODO(johnniwinther): Supported multiple output units.
      RecordedSourceInformationProcess process = strategy.processMap.keys.first;
      js.Node node = strategy.processMap[process]!;
      String code;
      LocationMap nodeMap;
      CodePositionRecorder codePositions;
      nodeMap = process.nodeToSourceLocationsMap;
      code = process.code;
      codePositions = process.codePositions;
      CodePointComputer visitor = CodePointComputer(
        sourceFileManager,
        code,
        nodeMap,
      );
      final outBuffer = NoopCodeOutput();
      SourceInformationProcessor sourceInformationProcessor =
          HelperOnlinePositionSourceInformationStrategy([
            visitor,
          ]).createProcessor(
            SourceMapperProviderImpl(outBuffer),
            const SourceInformationReader(),
          );

      js.Dart2JSJavaScriptPrintingContext context =
          js.Dart2JSJavaScriptPrintingContext(
            null,
            outBuffer,
            sourceInformationProcessor,
            const js.JavaScriptAnnotationMonitor(),
          );
      js.Printer printer = js.Printer(
        const js.JavaScriptPrintingOptions(),
        context,
      );
      printer.visit(node);
      List<CodePoint> codePoints = visitor.codePoints;
      mainSourceMapInfo = SourceMapInfo(
        null,
        code,
        node,
        codePoints,
        codePositions,
        nodeMap,
      );
    }

    return SourceMaps(
      compiler,
      sourceFileManager,
      mainSourceMapInfo,
      elementSourceMapInfos,
    );
  }
}

class SourceMaps {
  final Compiler compiler;
  final SourceFileManager sourceFileManager;
  // TODO(johnniwinther): Supported multiple output units.
  final SourceMapInfo? mainSourceMapInfo;
  final Map<MemberEntity, SourceMapInfo> elementSourceMapInfos;

  SourceMaps(
    this.compiler,
    this.sourceFileManager,
    this.mainSourceMapInfo,
    this.elementSourceMapInfos,
  );
}

/// Source mapping information for the JavaScript code of an [Element].
class SourceMapInfo {
  final String? name;
  final MemberEntity? element;
  final String code;
  final js.Node node;
  final List<CodePoint> codePoints;
  final CodePositionMap jsCodePositions;
  final LocationMap nodeMap;

  SourceMapInfo(
    this.element,
    this.code,
    this.node,
    this.codePoints,
    this.jsCodePositions,
    this.nodeMap,
  ) : this.name =
          element != null ? computeElementNameForSourceMaps(element) : '';

  @override
  String toString() {
    return '$name:$element';
  }
}

/// Collection of JavaScript nodes with their source mapped target offsets
/// and source locations.
abstract class LocationMap {
  Iterable<js.Node> get nodes;

  Map<int, List<SourceLocation>>? operator [](js.Node node);

  factory LocationMap.recorder() = _LocationRecorder;

  factory LocationMap.filter(Set<js.Node> nodes, LocationMap map) =
      _FilteredLocationMap;
}

class _LocationRecorder implements SourceMapper, LocationMap {
  final Map<js.Node, Map<int, List<SourceLocation>>> _nodeMap = {};

  @override
  void register(js.Node node, int codeOffset, SourceLocation sourceLocation) {
    _nodeMap
        .putIfAbsent(node, () => {})
        .putIfAbsent(codeOffset, () => [])
        .add(sourceLocation);
  }

  @override
  void registerPush(
    int codeOffset,
    SourceLocation? sourceLocation,
    String inlinedMethodName,
  ) {}

  @override
  void registerPop(int codeOffset, {bool isEmpty = false}) {}

  @override
  Iterable<js.Node> get nodes => _nodeMap.keys;

  @override
  Map<int, List<SourceLocation>>? operator [](js.Node node) {
    return _nodeMap[node];
  }
}

class _FilteredLocationMap implements LocationMap {
  final Set<js.Node> _nodes;
  final LocationMap map;

  _FilteredLocationMap(this._nodes, this.map);

  @override
  Iterable<js.Node> get nodes => map.nodes.where((n) => _nodes.contains(n));

  @override
  Map<int, List<SourceLocation>>? operator [](js.Node node) {
    return map[node];
  }
}

/// Visitor that computes the [CodePoint]s for source mapping locations.
class CodePointComputer extends TraceListener {
  final SourceFileManager sourceFileManager;
  final String code;
  final LocationMap nodeMap;
  List<CodePoint> codePoints = [];

  CodePointComputer(this.sourceFileManager, this.code, this.nodeMap);

  String nodeToString(js.Node node) {
    js.JavaScriptPrintingOptions options = js.JavaScriptPrintingOptions(
      shouldCompressOutput: true,
      preferSemicolonToNewlineInMinifiedOutput: true,
    );
    LenientPrintingContext printingContext = LenientPrintingContext();
    js.Printer(options, printingContext).visit(node);
    return printingContext.buffer.toString();
  }

  String positionToString(int position) {
    String line = code.substring(position);
    int nl = line.indexOf('\n');
    if (nl != -1) {
      line = line.substring(0, nl);
    }
    return line;
  }

  /// Called when [node] defines a step of the given [kind] at the given
  /// [offset] when the generated JavaScript code.
  @override
  void onStep(js.Node node, Offset offset, StepKind kind) {
    if (kind == StepKind.access) return;
    register(kind, node);
  }

  void register(StepKind kind, js.Node node, {bool expectInfo = true}) {
    String dartCodeFromSourceLocation(SourceLocation sourceLocation) {
      SourceFile? sourceFile = sourceFileManager.getSourceFile(
        sourceLocation.sourceUri,
      );
      if (sourceFile == null) {
        return sourceLocation.shortText;
      }
      return sourceFile.kernelSource
          .getTextLine(sourceLocation.line)!
          .substring(sourceLocation.column - 1)
          .trim();
    }

    void addLocation(
      SourceLocation? sourceLocation,
      String jsCode,
      int? targetOffset,
    ) {
      if (sourceLocation == null) {
        if (expectInfo) {
          final sourceInformation =
              node.sourceInformation as SourceInformation?;
          SourceLocation? sourceLocation;
          String? dartCode;
          if (sourceInformation != null) {
            sourceLocation = sourceInformation.sourceLocations.first;
            dartCode = dartCodeFromSourceLocation(sourceLocation);
          }
          codePoints.add(
            new CodePoint(
              kind,
              jsCode,
              targetOffset,
              sourceLocation,
              dartCode,
              isMissing: true,
            ),
          );
        }
      } else {
        codePoints.add(
          new CodePoint(
            kind,
            jsCode,
            targetOffset,
            sourceLocation,
            dartCodeFromSourceLocation(sourceLocation),
          ),
        );
      }
    }

    Map<int, List<SourceLocation>>? locationMap = nodeMap[node];
    if (locationMap == null) {
      addLocation(null, nodeToString(node), null);
    } else {
      locationMap.forEach((int targetOffset, List<SourceLocation> locations) {
        String jsCode = nodeToString(node);
        for (SourceLocation location in locations) {
          addLocation(location, jsCode, targetOffset);
        }
      });
    }
  }
}

/// A JavaScript code point and its mapped dart source location.
class CodePoint {
  final StepKind kind;
  final String jsCode;
  final int? targetOffset;
  final SourceLocation? sourceLocation;
  final String? dartCode;
  final bool isMissing;

  CodePoint(
    this.kind,
    this.jsCode,
    this.targetOffset,
    this.sourceLocation,
    this.dartCode, {
    this.isMissing = false,
  });

  @override
  String toString() {
    return 'CodePoint[kind=$kind,js=$jsCode,dart=$dartCode,'
        'location=$sourceLocation]';
  }
}

class IOSourceFileManager implements SourceFileManager {
  final Uri base;

  Map<Uri, SourceFile> sourceFiles = <Uri, SourceFile>{};

  IOSourceFileManager(this.base);

  @override
  SourceFile getSourceFile(Object? uri) {
    Uri absoluteUri;
    if (uri is Uri) {
      absoluteUri = base.resolveUri(uri);
    } else {
      absoluteUri = base.resolve(uri as String);
    }
    return sourceFiles.putIfAbsent(absoluteUri, () {
      String text = File.fromUri(absoluteUri).readAsStringSync();
      return StringSourceFile.fromUri(absoluteUri, text);
    });
  }
}
