// 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(
      minify: 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);
    });
  }
}
