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

// @dart = 2.10

library dart2js.js_emitter.startup_emitter.model_emitter;

import 'dart:convert' show JsonEncoder;

import 'package:js_runtime/shared/embedded_names.dart'
    show
        ARRAY_RTI_PROPERTY,
        DEFERRED_INITIALIZED,
        DEFERRED_LIBRARY_PARTS,
        DEFERRED_PART_URIS,
        DEFERRED_PART_HASHES,
        INITIALIZE_LOADED_HUNK,
        INTERCEPTORS_BY_TAG,
        IS_HUNK_INITIALIZED,
        IS_HUNK_LOADED,
        JsGetName,
        LEAF_TAGS,
        MANGLED_GLOBAL_NAMES,
        MANGLED_NAMES,
        METADATA,
        NATIVE_SUPERCLASS_TAG_NAME,
        RTI_UNIVERSE,
        RtiUniverseFieldNames,
        STARTUP_METRICS,
        TearOffParametersPropertyNames,
        TYPE_TO_INTERCEPTOR_MAP,
        TYPES;

import 'package:js_ast/src/precedence.dart' as js_precedence;

import '../../../compiler.dart';
import '../../common.dart';
import '../../common/elements.dart' show CommonElements, JElementEnvironment;
import '../../common/tasks.dart';
import '../../constants/values.dart'
    show ConstantValue, FunctionConstantValue, LateSentinelConstantValue;
import '../../deferred_load/output_unit.dart' show OutputUnit;
import '../../dump_info.dart';
import '../../elements/entities.dart';
import '../../elements/types.dart';
import '../../hash/sha1.dart' show Hasher;
import '../../io/code_output.dart';
import '../../io/location_provider.dart' show LocationCollector;
import '../../io/source_information.dart';
import '../../io/source_map_builder.dart' show SourceMapBuilder;
import '../../js/js.dart' as js;
import '../../js/size_estimator.dart';
import '../../js_backend/js_backend.dart'
    show Namer, ConstantEmitter, StringBackedName;
import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
import '../../js_backend/runtime_types.dart';
import '../../js_backend/runtime_types_codegen.dart';
import '../../js_backend/runtime_types_new.dart'
    show RecipeEncoder, RecipeEncoderImpl, Ruleset, RulesetEncoder;
import '../../js_backend/runtime_types_resolution.dart' show RuntimeTypesNeed;
import '../../js_backend/deferred_holder_expression.dart'
    show
        DeferredHolderExpressionFinalizer,
        DeferredHolderExpressionFinalizerImpl,
        DeferredHolderParameter,
        DeferredHolderResource,
        DeferredHolderResourceKind,
        mainResourceName;
import '../../js_backend/type_reference.dart'
    show
        TypeReferenceFinalizer,
        TypeReferenceFinalizerImpl,
        TypeReferenceResource;
import '../../js_backend/string_reference.dart'
    show
        StringReferenceFinalizer,
        StringReferenceFinalizerImpl,
        StringReferenceResource;
import '../../options.dart';
import '../../universe/class_hierarchy.dart' show ClassHierarchy;
import '../../universe/codegen_world_builder.dart' show CodegenWorld;
import '../../world.dart';
import '../code_emitter_task.dart';
import '../constant_ordering.dart' show ConstantOrdering;
import '../headers.dart';
import '../js_emitter.dart' show buildTearOffCode, NativeGenerator;
import '../model.dart';
import '../native_emitter.dart';
import 'fragment_merger.dart';

part 'fragment_emitter.dart';

class EmittedCodeFragment {
  final CodeFragment codeFragment;
  final js.Expression code;

  EmittedCodeFragment(this.codeFragment, this.code);
}

class ModelEmitter {
  final CompilerOptions _options;
  final DiagnosticReporter _reporter;
  final CompilerOutput _outputProvider;
  final DumpInfoTask _dumpInfoTask;
  final Namer _namer;
  final CompilerTask _task;
  final Emitter _emitter;
  ConstantEmitter constantEmitter;
  final NativeEmitter _nativeEmitter;
  final bool _shouldGenerateSourceMap;
  final JClosedWorld _closedWorld;
  final ConstantOrdering _constantOrdering;
  final SourceInformationStrategy _sourceInformationStrategy;
  final FragmentMerger fragmentMerger;

  // The full code that is written to each hunk part-file.
  final Map<OutputUnit, CodeOutput> emittedOutputBuffers = {};

  final Set<OutputUnit> omittedOutputUnits = {};

  List<PreFragment> preDeferredFragmentsForTesting;

  /// A mapping from the name of a defer import to all the fragments it
  /// depends on in a list of lists to be loaded in the order they appear.
  ///
  /// For example {"lib1": [[lib1_lib2_lib3], [lib1_lib2, lib1_lib3],
  /// [lib1]]} would mean that in order to load "lib1" first the hunk
  /// lib1_lib2_lib2 should be loaded, then the hunks lib1_lib2 and lib1_lib3
  /// can be loaded in parallel. And fially lib1 can be loaded.
  final Map<String, List<FinalizedFragment>> finalizedFragmentsToLoad = {};

  /// Similar to the above map, but more granular as each [FinalizedFragment]
  /// may have multiple CodeFragments.
  final Map<String, List<CodeFragment>> codeFragmentsToLoad = {};

  /// For deferred loading we communicate the initializers via this global var.
  static const String deferredInitializersGlobal =
      r"$__dart_deferred_initializers__";

  static const String startupMetricsGlobal = r'$__dart_startupMetrics';

  static const String partExtension = "part";
  static const String deferredExtension = "part.js";

  static const String typeNameProperty = r"builtin$cls";

  ModelEmitter(
      this._options,
      this._reporter,
      this._outputProvider,
      this._dumpInfoTask,
      this._namer,
      this._closedWorld,
      this._task,
      this._emitter,
      this._nativeEmitter,
      this._sourceInformationStrategy,
      RecipeEncoder rtiRecipeEncoder,
      this._shouldGenerateSourceMap)
      : _constantOrdering = ConstantOrdering(_closedWorld.sorter),
        fragmentMerger = FragmentMerger(_options,
            _closedWorld.elementEnvironment, _closedWorld.outputUnitData) {
    this.constantEmitter = ConstantEmitter(
        _options,
        _namer,
        _closedWorld.commonElements,
        _closedWorld.elementEnvironment,
        _closedWorld.rtiNeed,
        rtiRecipeEncoder,
        _closedWorld.fieldAnalysis,
        _emitter,
        this.generateConstantReference,
        constantListGenerator);
  }

  js.Expression constantListGenerator(js.Expression array) {
    // TODO(floitsch): remove hard-coded name.
    return js.js('makeConstList(#)', [array]);
  }

  bool isConstantInlinedOrAlreadyEmitted(ConstantValue constant) {
    if (constant.isFunction) return true; // Already emitted.
    if (constant.isPrimitive) return true; // Inlined.
    if (constant.isDummy) return true; // Inlined.
    if (constant is LateSentinelConstantValue) return true; // Inlined.
    return false;
  }

  // TODO(floitsch): copied from OldEmitter. Adjust or share.
  int compareConstants(ConstantValue a, ConstantValue b) {
    // Inlined constants don't affect the order and sometimes don't even have
    // names.
    int cmp1 = isConstantInlinedOrAlreadyEmitted(a) ? 0 : 1;
    int cmp2 = isConstantInlinedOrAlreadyEmitted(b) ? 0 : 1;
    if (cmp1 + cmp2 < 2) return cmp1 - cmp2;

    // Emit constant interceptors first. Constant interceptors for primitives
    // might be used by code that builds other constants.  See Issue 18173.
    if (a.isInterceptor != b.isInterceptor) {
      return a.isInterceptor ? -1 : 1;
    }

    // Sorting by the long name clusters constants with the same constructor
    // which compresses a tiny bit better.
    int r = _namer.constantLongName(a).compareTo(_namer.constantLongName(b));
    if (r != 0) return r;

    // Resolve collisions in the long name by using a structural order.
    return _constantOrdering.compare(a, b);
  }

  js.Expression generateConstantReference(ConstantValue value) {
    if (value.isFunction) {
      FunctionConstantValue functionConstant = value;
      return _emitter.staticClosureAccess(functionConstant.element);
    }

    // We are only interested in the "isInlined" part, but it does not hurt to
    // test for the other predicates.
    if (isConstantInlinedOrAlreadyEmitted(value)) {
      return constantEmitter.generate(value);
    }
    return js.js('#.#',
        [_namer.globalObjectForConstant(value), _namer.constantName(value)]);
  }

  bool get shouldMergeFragments => _options.mergeFragmentsThreshold != null;

  int emitProgram(Program program, CodegenWorld codegenWorld) {
    MainFragment mainFragment = program.fragments.first;
    List<DeferredFragment> deferredFragments =
        List<DeferredFragment>.from(program.deferredFragments);

    FragmentEmitter fragmentEmitter = FragmentEmitter(
        _options,
        _dumpInfoTask,
        _namer,
        _emitter,
        constantEmitter,
        this,
        _nativeEmitter,
        _closedWorld,
        codegenWorld);

    // In order to get size estimates, we partially emit deferred fragments.
    List<OutputUnit> outputUnits = [];
    List<PreFragment> preDeferredFragments = [];
    _task.measureSubtask('emit prefragments', () {
      for (var fragment in deferredFragments) {
        var preFragment =
            fragmentEmitter.emitPreFragment(fragment, shouldMergeFragments);
        outputUnits.add(fragment.outputUnit);
        preDeferredFragments.add(preFragment);
      }
    });

    // Sort output units so they are in a canonical order and generate a map of
    // loadId to list of OutputUnits to load.
    outputUnits.sort();
    var outputUnitsToLoad =
        fragmentMerger.computeOutputUnitsToLoad(outputUnits);

    // If we are going to merge, then we attach dependencies to each PreFragment
    // and merge.
    if (shouldMergeFragments) {
      preDeferredFragments = _task.measureSubtask('merge fragments', () {
        fragmentMerger.attachDependencies(outputUnits, preDeferredFragments);
        return fragmentMerger.mergeFragments(preDeferredFragments);
      });
    }

    // If necessary, we retain the merged PreFragments for testing.
    if (retainDataForTesting) {
      preDeferredFragmentsForTesting = preDeferredFragments;
    }

    // Finalize and emit fragments.
    Map<OutputUnit, CodeFragment> outputUnitMap = {};
    Map<CodeFragment, FinalizedFragment> codeFragmentMap = {};
    Map<FinalizedFragment, List<EmittedCodeFragment>> deferredFragmentsCode =
        {};
    for (var preDeferredFragment in preDeferredFragments) {
      var finalizedFragment =
          preDeferredFragment.finalize(program, outputUnitMap, codeFragmentMap);
      for (var codeFragment in finalizedFragment.codeFragments) {
        js.Expression fragmentCode =
            fragmentEmitter.emitCodeFragment(codeFragment);
        if (fragmentCode != null) {
          (deferredFragmentsCode[finalizedFragment] ??= [])
              .add(EmittedCodeFragment(codeFragment, fragmentCode));
        } else {
          omittedOutputUnits.addAll(codeFragment.outputUnits);
        }
      }
    }

    // With all deferred fragments finalized, we can now compute a map of
    // loadId to the files(FinalizedFragments) which need to be loaded.
    fragmentMerger.computeFragmentsToLoad(
        outputUnitsToLoad,
        outputUnitMap,
        codeFragmentMap,
        omittedOutputUnits,
        codeFragmentsToLoad,
        finalizedFragmentsToLoad);

    // Emit main Fragment.
    var deferredLoadingState = DeferredLoadingState();
    js.Statement mainCode = fragmentEmitter.emitMainFragment(
        program, finalizedFragmentsToLoad, deferredLoadingState);

    // Count tokens and run finalizers.
    js.TokenCounter counter = js.TokenCounter();
    for (var emittedFragments in deferredFragmentsCode.values) {
      for (var emittedFragment in emittedFragments) {
        counter.countTokens(emittedFragment.code);
      }
    }
    counter.countTokens(mainCode);

    program.finalizers.forEach((js.TokenFinalizer f) => f.finalizeTokens());

    // TODO(sra): This is where we know if the types (and potentially other
    // deferred ASTs inside the parts) have any contents. We should wait until
    // this point to decide if a part is empty.

    Map<CodeFragment, String> codeFragmentHashes =
        _task.measureSubtask('write fragments', () {
      return writeFinalizedFragments(deferredFragmentsCode);
    });

    // Now that we have written the deferred hunks, we can create the deferred
    // loading data.
    fragmentEmitter.finalizeDeferredLoadingData(codeFragmentsToLoad,
        codeFragmentMap, codeFragmentHashes, deferredLoadingState);

    _task.measureSubtask('write fragments', () {
      writeMainFragment(mainFragment, mainCode,
          isSplit: program.deferredFragments.isNotEmpty ||
              _options.experimentalTrackAllocations);
    });

    if (_closedWorld.backendUsage.requiresPreamble &&
        !_closedWorld.backendUsage.isHtmlLoaded) {
      _reporter.reportHintMessage(NO_LOCATION_SPANNABLE, MessageKind.PREAMBLE);
    }

    if (_options.deferredMapUri != null) {
      writeDeferredMap();
    }

    // Return the total program size.
    return emittedOutputBuffers.values.fold(0, (a, b) => a + b.length);
  }

  /// Generates a simple header that provides the compiler's build id.
  js.Comment buildGeneratedBy() {
    final flavor = StringBuffer();
    flavor.write(_options.nullSafetyMode);
    if (_options.trustPrimitives) flavor.write(', trust primitives');
    if (_options.omitImplicitChecks) flavor.write(', omit checks');
    if (_options.laxRuntimeTypeToString) {
      flavor.write(', lax runtime type');
    }
    var featureString = _options.features.flavorString();
    if (featureString.isNotEmpty) flavor.write(', $featureString');
    return js.Comment(generatedBy(_options, flavor: '$flavor'));
  }

  List<js.Statement> buildDeferredInitializerGlobal() {
    return [
      js.js.statement(
          'self.#deferredInitializers = '
          'self.#deferredInitializers || Object.create(null);',
          {'deferredInitializers': deferredInitializersGlobal}),
      if (_options.experimentalTrackAllocations)
        js.js.statement(
            'self.#deferredInitializers["allocations"] = '
            'self.#deferredInitializers["allocations"] '
            '|| Object.create(null)',
            {'deferredInitializers': deferredInitializersGlobal})
    ];
  }

  js.Statement buildStartupMetrics() {
    // We want the code that initializes the startup metrics to execute as early
    // as possible, so it is placed ahead of the main program IIFE instead of,
    // e.g. as a parameter of the IIFE. It is OK to use a top-level variable,
    // since the IIFE immediately reads the variable.
    return js.js.statement('''
var ${startupMetricsGlobal} =
(function(){
  // The timestamp metrics use `performance.now()`. We feature-detect and
  // fall back on `Date.now()` for JavaScript run in a non-browser evironment.
  var _performance =
      (typeof performance == "object" &&
       performance != null &&
       typeof performance.now == "function")
          ? performance
          : Date;
  var metrics = {
    a: [],
    now: function() { return _performance.now() },
    add: function(name) { this.a.push(name, this.now()); }
  };
  metrics.add('firstMs');
  return metrics;
})();''');
  }

  // Writes the given [fragment]'s [code] into a file.
  //
  // Updates the shared [outputBuffers] field with the output.
  void writeMainFragment(MainFragment fragment, js.Statement code,
      {bool isSplit}) {
    LocationCollector locationCollector;
    List<CodeOutputListener> codeOutputListeners;
    if (_shouldGenerateSourceMap) {
      _task.measureSubtask('source-maps', () {
        locationCollector = LocationCollector();
        codeOutputListeners = [locationCollector];
      });
    }

    CodeOutput mainOutput = StreamCodeOutput(
        _outputProvider.createOutputSink('', 'js', OutputType.js),
        codeOutputListeners);
    emittedOutputBuffers[fragment.outputUnit] = mainOutput;

    js.Program program = js.Program([
      buildGeneratedBy(),
      js.Comment(HOOKS_API_USAGE),
      if (isSplit) ...buildDeferredInitializerGlobal(),
      if (_closedWorld.backendUsage.requiresStartupMetrics)
        buildStartupMetrics(),
      code
    ]);

    CodeBuffer buffer = js.createCodeBuffer(
        program, _options, _sourceInformationStrategy,
        monitor: _dumpInfoTask);
    _task.measureSubtask('emit buffers', () {
      mainOutput.addBuffer(buffer);
    });

    if (_shouldGenerateSourceMap) {
      _task.measureSubtask('source-maps', () {
        mainOutput.add(SourceMapBuilder.generateSourceMapTag(
            _options.sourceMapUri, _options.outputUri));
      });
    }

    mainOutput.close();

    if (_shouldGenerateSourceMap) {
      _task.measureSubtask('source-maps', () {
        SourceMapBuilder.outputSourceMap(
            mainOutput,
            locationCollector,
            _namer.createMinifiedGlobalNameMap(),
            _namer.createMinifiedInstanceNameMap(),
            '',
            _options.sourceMapUri,
            _options.outputUri,
            _outputProvider);
      });
    }
  }

  /// Writes all [FinalizedFragments] to files, returning a map of
  /// [CodeFragment] to their initialization hashes.
  Map<CodeFragment, String> writeFinalizedFragments(
      Map<FinalizedFragment, List<EmittedCodeFragment>> fragmentsCode) {
    Map<CodeFragment, String> fragmentHashes = {};
    fragmentsCode.forEach((fragment, code) {
      writeFinalizedFragment(fragment, code, fragmentHashes);
    });
    return fragmentHashes;
  }

  /// Writes a single [FinalizedFragment] and all of its [CodeFragments] to
  /// file, updating the [fragmentHashes] map as necessary.
  void writeFinalizedFragment(
      FinalizedFragment fragment,
      List<EmittedCodeFragment> fragmentCode,
      Map<CodeFragment, String> fragmentHashes) {
    List<CodeOutputListener> outputListeners = [];
    LocationCollector locationCollector;
    if (_shouldGenerateSourceMap) {
      _task.measureSubtask('source-maps', () {
        locationCollector = LocationCollector();
        outputListeners.add(locationCollector);
      });
    }

    String outputFileName = fragment.outputFileName;
    CodeOutput output = StreamCodeOutput(
        _outputProvider.createOutputSink(
            outputFileName, deferredExtension, OutputType.jsPart),
        outputListeners);

    writeCodeFragments(fragmentCode, fragmentHashes, output);

    if (_shouldGenerateSourceMap) {
      _task.measureSubtask('source-maps', () {
        Uri mapUri, partUri;
        Uri sourceMapUri = _options.sourceMapUri;
        Uri outputUri = _options.outputUri;
        String partName = "$outputFileName.$partExtension";
        String hunkFileName = "$outputFileName.$deferredExtension";

        if (sourceMapUri != null) {
          String mapFileName = hunkFileName + ".map";
          List<String> mapSegments = sourceMapUri.pathSegments.toList();
          mapSegments[mapSegments.length - 1] = mapFileName;
          mapUri = _options.sourceMapUri.replace(pathSegments: mapSegments);
        }

        if (outputUri != null) {
          List<String> partSegments = outputUri.pathSegments.toList();
          partSegments[partSegments.length - 1] = hunkFileName;
          partUri = _options.outputUri.replace(pathSegments: partSegments);
        }

        output.add(SourceMapBuilder.generateSourceMapTag(mapUri, partUri));
        output.close();
        SourceMapBuilder.outputSourceMap(output, locationCollector, {}, {},
            partName, mapUri, partUri, _outputProvider);
      });
    } else {
      output.close();
    }
  }

  /// Writes a list of [CodeFragments] to [CodeOutput].
  void writeCodeFragments(List<EmittedCodeFragment> fragmentCode,
      Map<CodeFragment, String> fragmentHashes, CodeOutput output) {
    bool isFirst = true;
    for (var emittedCodeFragment in fragmentCode) {
      var codeFragment = emittedCodeFragment.codeFragment;
      var code = emittedCodeFragment.code;
      for (var outputUnit in codeFragment.outputUnits) {
        emittedOutputBuffers[outputUnit] = output;
      }
      fragmentHashes[codeFragment] = writeCodeFragment(output, code, isFirst);
      isFirst = false;
    }
  }

  // Writes the given [fragment]'s [code] into a file.
  //
  // Returns the deferred fragment's hash.
  //
  // Updates the shared [outputBuffers] field with the output.
  String writeCodeFragment(
      CodeOutput output, js.Expression code, bool isFirst) {
    // The [code] contains the function that must be invoked when the deferred
    // hunk is loaded.
    // That function must be in a map from its hashcode to the function. Since
    // we don't know the hash before we actually emit the code we store the
    // function in a temporary field first:
    //
    //   deferredInitializer.current = <pretty-printed code>;
    //   deferredInitializer[<hash>] = deferredInitializer.current;

    js.Program program = js.Program([
      if (isFirst) buildGeneratedBy(),
      if (isFirst) ...buildDeferredInitializerGlobal(),
      if (_options.experimentalTrackAllocations)
        js.js.statement("var allocations = #deferredGlobal['allocations']",
            {'deferredGlobal': deferredInitializersGlobal}),
      js.js.statement('$deferredInitializersGlobal.current = #', code)
    ]);

    Hasher hasher = Hasher();
    CodeBuffer buffer = js.createCodeBuffer(
        program, _options, _sourceInformationStrategy,
        monitor: _dumpInfoTask, listeners: [hasher]);
    _task.measureSubtask('emit buffers', () {
      output.addBuffer(buffer);
    });

    // Make a unique hash of the code (before the sourcemaps are added)
    // This will be used to retrieve the initializing function from the global
    // variable.
    String hash = hasher.getHash();

    // Now we copy the deferredInitializer.current into its correct hash.
    output.add('\n${deferredInitializersGlobal}["$hash"] = '
        '${deferredInitializersGlobal}.current\n');
    return hash;
  }

  /// Writes a mapping from library-name to hunk files.
  ///
  /// The output is written into a separate file that can be used by outside
  /// tools.
  void writeDeferredMap() {
    Map<String, dynamic> mapping = {};
    // Json does not support comments, so we embed the explanation in the
    // data.
    mapping["_comment"] = "This mapping shows which compiled `.js` files are "
        "needed for a given deferred library import.";
    mapping.addAll(fragmentMerger.computeDeferredMap(finalizedFragmentsToLoad));
    _outputProvider.createOutputSink(
        _options.deferredMapUri.path, '', OutputType.deferredMap)
      ..add(const JsonEncoder.withIndent("  ").convert(mapping))
      ..close();
  }
}
