// 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 dart2js.js_emitter.startup_emitter.model_emitter;

import 'dart:convert' show JsonEncoder;
import 'dart:math' show Random;

import 'package:js_runtime/shared/embedded_names.dart'
    show
        DEFERRED_INITIALIZED,
        DEFERRED_LIBRARY_PARTS,
        DEFERRED_PART_URIS,
        DEFERRED_PART_HASHES,
        GET_TYPE_FROM_NAME,
        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,
        TYPE_TO_INTERCEPTOR_MAP,
        TYPES;

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

import '../../../compiler_new.dart';
import '../../common.dart';
import '../../common/tasks.dart';
import '../../constants/values.dart'
    show ConstantValue, FunctionConstantValue, NullConstantValue;
import '../../common_elements.dart' show CommonElements;
import '../../dump_info.dart';
import '../../elements/entities.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_backend/js_backend.dart'
    show Namer, ConstantEmitter, StringBackedName;
import '../../js_backend/js_interop_analysis.dart' as jsInteropAnalysis;
import '../../js_backend/runtime_types.dart';
import '../../options.dart';
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';

part 'fragment_emitter.dart';

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 bool _shouldGenerateSourceMap;
  final JClosedWorld _closedWorld;
  final ConstantOrdering _constantOrdering;
  final SourceInformationStrategy _sourceInformationStrategy;

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

  Set<Fragment> omittedFragments = Set();

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

  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._sourceInformationStrategy,
      RuntimeTypesEncoder rtiEncoder,
      this._shouldGenerateSourceMap)
      : _constantOrdering = new ConstantOrdering(_closedWorld.sorter) {
    this._constantEmitter = new ConstantEmitter(
        _options,
        _closedWorld.commonElements,
        _closedWorld.elementEnvironment,
        _closedWorld.rtiNeed,
        rtiEncoder,
        _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.
    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)]);
  }

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

    FragmentEmitter fragmentEmitter = new FragmentEmitter(
        _options,
        _dumpInfoTask,
        _namer,
        _emitter,
        _constantEmitter,
        this,
        _closedWorld,
        codegenWorld);

    var deferredLoadingState = new DeferredLoadingState();
    js.Statement mainCode =
        fragmentEmitter.emitMainFragment(program, deferredLoadingState);

    Map<DeferredFragment, js.Expression> deferredFragmentsCode = {};

    for (DeferredFragment fragment in deferredFragments) {
      js.Expression types =
          program.metadataTypesForOutputUnit(fragment.outputUnit);
      js.Expression fragmentCode = fragmentEmitter.emitDeferredFragment(
          fragment, types, program.holders);
      if (fragmentCode != null) {
        deferredFragmentsCode[fragment] = fragmentCode;
      } else {
        omittedFragments.add(fragment);
      }
    }

    js.TokenCounter counter = new js.TokenCounter();
    deferredFragmentsCode.values.forEach(counter.countTokens);
    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<DeferredFragment, String> hunkHashes =
        _task.measureSubtask('write fragments', () {
      return writeDeferredFragments(deferredFragmentsCode);
    });

    // Now that we have written the deferred hunks, we can create the deferred
    // loading data.
    fragmentEmitter.finalizeDeferredLoadingData(
        program.loadMap, hunkHashes, deferredLoadingState);

    _task.measureSubtask('write fragments', () {
      writeMainFragment(mainFragment, mainCode,
          isSplit: program.deferredFragments.isNotEmpty ||
              program.hasSoftDeferredClasses ||
              _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 outputBuffers.values.fold(0, (a, b) => a + b.length);
  }

  /// Generates a simple header that provides the compiler's build id.
  js.Comment buildGeneratedBy() {
    StringBuffer flavor = new StringBuffer();
    flavor.write('fast startup emitter');
    // TODO(johnniwinther): Remove this flavor.
    flavor.write(', strong');
    if (_options.trustPrimitives) flavor.write(', trust primitives');
    if (_options.omitImplicitChecks) flavor.write(', omit checks');
    if (_options.laxRuntimeTypeToString) {
      flavor.write(', lax runtime type');
    }
    if (_options.useContentSecurityPolicy) flavor.write(', CSP');
    return new js.Comment(generatedBy(_options, flavor: '$flavor'));
  }

  /// Writes all deferred fragment's code into files.
  ///
  /// Returns a map from fragment to its hashcode (as used for the deferred
  /// library code).
  ///
  /// Updates the shared [outputBuffers] field with the output.
  Map<DeferredFragment, String> writeDeferredFragments(
      Map<DeferredFragment, js.Expression> fragmentsCode) {
    Map<DeferredFragment, String> hunkHashes = {};

    fragmentsCode.forEach((DeferredFragment fragment, js.Expression code) {
      hunkHashes[fragment] = writeDeferredFragment(fragment, code);
    });

    return hunkHashes;
  }

  js.Statement buildDeferredInitializerGlobal() {
    return js.js.statement(
        'self.#deferredInitializers = '
        'self.#deferredInitializers || Object.create(null);',
        {'deferredInitializers': deferredInitializersGlobal});
  }

  // 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 = new LocationCollector();
        codeOutputListeners = <CodeOutputListener>[locationCollector];
      });
    }

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

    js.Program program = new js.Program([
      buildGeneratedBy(),
      new js.Comment(HOOKS_API_USAGE),
      isSplit ? buildDeferredInitializerGlobal() : new js.Block.empty(),
      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 the given [fragment]'s [code] into a file.
  //
  // Returns the deferred fragment's hash.
  //
  // Updates the shared [outputBuffers] field with the output.
  String writeDeferredFragment(DeferredFragment fragment, js.Expression code) {
    List<CodeOutputListener> outputListeners = [];
    Hasher hasher = new Hasher();
    outputListeners.add(hasher);

    LocationCollector locationCollector;
    if (_shouldGenerateSourceMap) {
      _task.measureSubtask('source-maps', () {
        locationCollector = new LocationCollector();
        outputListeners.add(locationCollector);
      });
    }

    String hunkPrefix = fragment.outputFileName;

    CodeOutput output = new StreamCodeOutput(
        _outputProvider.createOutputSink(
            hunkPrefix, deferredExtension, OutputType.jsPart),
        outputListeners);

    outputBuffers[fragment] = output;

    // 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 = new js.Program([
      buildGeneratedBy(),
      buildDeferredInitializerGlobal(),
      js.js.statement('$deferredInitializersGlobal.current = #', code)
    ]);

    CodeBuffer buffer = js.createCodeBuffer(
        program, _options, _sourceInformationStrategy,
        monitor: _dumpInfoTask);
    _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');

    if (_shouldGenerateSourceMap) {
      _task.measureSubtask('source-maps', () {
        Uri mapUri, partUri;
        Uri sourceMapUri = _options.sourceMapUri;
        Uri outputUri = _options.outputUri;
        String partName = "$hunkPrefix.$partExtension";
        String hunkFileName = "$hunkPrefix.$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();
    }

    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(_closedWorld.outputUnitData.computeDeferredMap(
        _options, _closedWorld.elementEnvironment,
        omittedUnits:
            omittedFragments.map((fragment) => fragment.outputUnit).toSet()));
    _outputProvider.createOutputSink(
        _options.deferredMapUri.path, '', OutputType.deferredMap)
      ..add(const JsonEncoder.withIndent("  ").convert(mapping))
      ..close();
  }
}
