// Copyright (c) 2021, 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:js_ast/src/precedence.dart' as js show PRIMARY;

import '../common_elements.dart' show JCommonElements;
import '../elements/entities.dart';
import '../js/js.dart' as js;
import '../serialization/serialization.dart';
import '../util/util.dart';

import 'namer.dart';

// TODO(joshualitt): Figure out how to subsume more of the modular naming
// framework into this approach. For example, we are still creating ModularNames
// for the entity referenced in the DeferredHolderExpression.
enum DeferredHolderExpressionKind {
  globalObjectForStaticState,
  globalObjectForConstants,
  globalObjectForLibrary,
  globalObjectForClass,
  globalObjectForMember,
}

/// A [DeferredHolderExpression] is a deferred JavaScript expression determined
/// by the finalization of holders. It is the injection point for data or
/// code to related to holders. The actual [Expression] contained within the
/// [DeferredHolderExpression] is determined by the
/// [DeferredHolderExpressionKind], eventually, most will be a [PropertyAccess]
/// but currently all are [VariableUse]s.
class DeferredHolderExpression extends js.DeferredExpression
    implements js.AstContainer {
  static const String tag = 'deferred-holder-expression';

  final DeferredHolderExpressionKind kind;
  final Entity entity;
  js.Expression _value;

  @override
  final js.JavaScriptNodeSourceInformation sourceInformation;

  DeferredHolderExpression(this.kind, this.entity) : sourceInformation = null;
  DeferredHolderExpression._(
      this.kind, this.entity, this._value, this.sourceInformation);
  factory DeferredHolderExpression.forConstants() {
    return DeferredHolderExpression(
        DeferredHolderExpressionKind.globalObjectForConstants, null);
  }

  factory DeferredHolderExpression.forStaticState() {
    return DeferredHolderExpression(
        DeferredHolderExpressionKind.globalObjectForStaticState, null);
  }

  factory DeferredHolderExpression.readFromDataSource(DataSource source) {
    source.begin(tag);
    var kind = source.readEnum(DeferredHolderExpressionKind.values);
    Entity entity;
    switch (kind) {
      case DeferredHolderExpressionKind.globalObjectForLibrary:
        entity = source.readLibrary();
        break;
      case DeferredHolderExpressionKind.globalObjectForClass:
        entity = source.readClass();
        break;
      case DeferredHolderExpressionKind.globalObjectForMember:
        entity = source.readMember();
        break;
      case DeferredHolderExpressionKind.globalObjectForStaticState:
      case DeferredHolderExpressionKind.globalObjectForConstants:
        // no entity.
        break;
    }
    source.end(tag);
    return DeferredHolderExpression(kind, entity);
  }

  void writeToDataSink(DataSink sink) {
    sink.begin(tag);
    sink.writeEnum(kind);
    switch (kind) {
      case DeferredHolderExpressionKind.globalObjectForLibrary:
        sink.writeLibrary(entity);
        break;
      case DeferredHolderExpressionKind.globalObjectForClass:
        sink.writeClass(entity);
        break;
      case DeferredHolderExpressionKind.globalObjectForMember:
        sink.writeMember(entity);
        break;
      case DeferredHolderExpressionKind.globalObjectForStaticState:
      case DeferredHolderExpressionKind.globalObjectForConstants:
        // no entity.
        break;
    }
    sink.end(tag);
  }

  set value(js.Expression value) {
    assert(!isFinalized && value != null);
    _value = value;
  }

  @override
  js.Expression get value {
    assert(isFinalized, '$this is unassigned');
    return _value;
  }

  @override
  bool get isFinalized => _value != null;

  @override
  DeferredHolderExpression withSourceInformation(
      js.JavaScriptNodeSourceInformation newSourceInformation) {
    if (newSourceInformation == sourceInformation) return this;
    if (newSourceInformation == null) return this;
    return DeferredHolderExpression._(
        kind, entity, _value, newSourceInformation);
  }

  @override
  int get precedenceLevel => _value?.precedenceLevel ?? js.PRIMARY;

  @override
  int get hashCode {
    return Hashing.objectsHash(kind, entity);
  }

  @override
  bool operator ==(Object other) {
    if (identical(this, other)) return true;
    return other is DeferredHolderExpression &&
        kind == other.kind &&
        entity == other.entity;
  }

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('DeferredHolderExpression(kind=$kind,entity=$entity,');
    sb.write('value=$_value)');
    return sb.toString();
  }

  @override
  Iterable<js.Node> get containedNodes => isFinalized ? [_value] : const [];
}

/// A [DeferredHolderParameter] is a deferred JavaScript expression determined
/// by the finalization of holders. It is the injection point for data or
/// code to related to holders. This class does not support serialization.
/// TODO(joshualitt): Today this exists just for the static state holder.
/// Ideally we'd be able to treat the static state holder like other holders.
class DeferredHolderParameter extends js.Expression implements js.Parameter {
  String _name;

  @override
  final bool allowRename = false;

  @override
  final js.JavaScriptNodeSourceInformation sourceInformation;

  DeferredHolderParameter() : sourceInformation = null;
  DeferredHolderParameter._(this._name, this.sourceInformation);

  set name(String name) {
    assert(!isFinalized && name != null);
    _name = name;
  }

  @override
  String get name {
    assert(isFinalized, '$this is unassigned');
    return _name;
  }

  @override
  bool get isFinalized => _name != null;

  @override
  DeferredHolderParameter withSourceInformation(
      js.JavaScriptNodeSourceInformation newSourceInformation) {
    if (newSourceInformation == sourceInformation) return this;
    if (newSourceInformation == null) return this;
    return DeferredHolderParameter._(_name, newSourceInformation);
  }

  @override
  int get precedenceLevel => js.PRIMARY;

  @override
  T accept<T>(js.NodeVisitor<T> visitor) => visitor.visitParameter(this);

  @override
  R accept1<R, A>(js.NodeVisitor1<R, A> visitor, A arg) =>
      visitor.visitParameter(this, arg);

  @override
  void visitChildren<T>(js.NodeVisitor<T> visitor) {}

  @override
  void visitChildren1<R, A>(js.NodeVisitor1<R, A> visitor, A arg) {}

  @override
  String toString() {
    StringBuffer sb = new StringBuffer();
    sb.write('DeferredHolderParameter(name=$_name)');
    return sb.toString();
  }
}

enum DeferredHolderResourceKind {
  declaration,
  update,
}

/// A [DeferredHolderResource] is a deferred JavaScript statement determined by
/// the finalization of holders. It is the injection point for data or
/// code to holders. The actual [Statement] contained with the
/// [DeferredHolderResource] will be determined by the
/// [DeferredHolderResourceKind]. These [Statement]s differ considerably
/// depending on where they are used in the AST. This class does not support
/// serialization.
class DeferredHolderResource extends js.DeferredStatement
    implements js.AstContainer {
  DeferredHolderResourceKind kind;
  Map<Entity, List<js.Property>> holderCode;
  bool initializeEmptyHolders;
  js.Statement _statement;

  @override
  final js.JavaScriptNodeSourceInformation sourceInformation;

  DeferredHolderResource(this.kind,
      {this.holderCode: const {}, this.initializeEmptyHolders: false})
      : sourceInformation = null;

  DeferredHolderResource._(this.kind, this.holderCode,
      this.initializeEmptyHolders, this._statement, this.sourceInformation);

  set statement(js.Statement statement) {
    assert(!isFinalized && statement != null);
    _statement = statement;
  }

  @override
  js.Statement get statement {
    assert(isFinalized, 'DeferredHolderResource is unassigned');
    return _statement;
  }

  @override
  bool get isFinalized => _statement != null;

  @override
  DeferredHolderResource withSourceInformation(
      js.JavaScriptNodeSourceInformation newSourceInformation) {
    if (newSourceInformation == sourceInformation) return this;
    if (newSourceInformation == null) return this;
    return DeferredHolderResource._(kind, holderCode, initializeEmptyHolders,
        _statement, newSourceInformation);
  }

  @override
  Iterable<js.Node> get containedNodes => isFinalized ? [_statement] : const [];

  @override
  void visitChildren<T>(js.NodeVisitor<T> visitor) {
    _statement?.accept<T>(visitor);
  }

  @override
  void visitChildren1<R, A>(js.NodeVisitor1<R, A> visitor, A arg) {
    _statement?.accept1<R, A>(visitor, arg);
  }
}

abstract class DeferredHolderExpressionFinalizer {
  /// Collects DeferredHolderExpressions from the JavaScript
  /// AST [code];
  void addCode(js.Node code);

  /// Performs analysis on all collected DeferredHolderExpression nodes
  /// finalizes the values to expressions to access the holders.
  void finalize();
}

/// [DeferredHolderExpressionFinalizerImpl] finalizes
/// [DeferredHolderExpression]s, [DeferredHolderParameter]s,
/// [DeferredHolderResource]s, [DeferredHolderResourceExpression]s.
class DeferredHolderExpressionFinalizerImpl
    implements DeferredHolderExpressionFinalizer {
  _DeferredHolderExpressionCollectorVisitor _visitor;
  final List<DeferredHolderExpression> holderReferences = [];
  final List<DeferredHolderParameter> holderParameters = [];
  final List<DeferredHolderResource> holderResources = [];
  final Set<String> _uniqueHolders = {};
  final List<String> _holders = [];
  final Map<Entity, String> _entityMap = {};
  final JCommonElements _commonElements;

  DeferredHolderExpressionFinalizerImpl(this._commonElements) {
    _visitor = _DeferredHolderExpressionCollectorVisitor(this);
  }

  @override
  void addCode(js.Node code) {
    code.accept(_visitor);
  }

  final List<String> userGlobalObjects =
      new List.from(Namer.reservedGlobalObjectNames)
        ..remove('C')
        ..remove('H')
        ..remove('J')
        ..remove('P')
        ..remove('W');

  /// Returns the [reservedGlobalObjectNames] for [library].
  String globalObjectForLibrary(LibraryEntity library) {
    if (library == _commonElements.interceptorsLibrary) return 'J';
    Uri uri = library.canonicalUri;
    if (uri.scheme == 'dart') {
      if (uri.path == 'html') return 'W';
      if (uri.path.startsWith('_')) return 'H';
      return 'P';
    }
    return userGlobalObjects[library.name.hashCode % userGlobalObjects.length];
  }

  /// Returns true if [element] is stored in the static state holder
  /// ([staticStateHolder]).  We intend to store only mutable static state
  /// there, whereas constants are stored in 'C'. Functions, accessors,
  /// classes, etc. are stored in one of the other objects in
  /// [reservedGlobalObjectNames].
  bool _isPropertyOfStaticStateHolder(MemberEntity element) {
    // TODO(ahe): Make sure this method's documentation is always true and
    // remove the word "intend".
    return element.isField;
  }

  String globalObjectForMember(MemberEntity entity) {
    if (_isPropertyOfStaticStateHolder(entity)) {
      return globalObjectForStaticState();
    } else {
      return globalObjectForLibrary(entity.library);
    }
  }

  String globalObjectForClass(ClassEntity entity) {
    return globalObjectForLibrary(entity.library);
  }

  String globalObjectForStaticState() => r'$';

  String globalObjectForConstants() => 'C';

  String globalObjectForEntity(Entity entity) {
    if (entity is MemberEntity) {
      return globalObjectForMember(entity);
    } else if (entity is ClassEntity) {
      return globalObjectForLibrary(entity.library);
    } else {
      assert(entity is LibraryEntity);
      return globalObjectForLibrary(entity);
    }
  }

  /// Registers an [Entity] with a specific [holder].
  void registerHolderUse(String holder, Entity entity) {
    if (_uniqueHolders.add(holder)) _holders.add(holder);
    if (entity != null) {
      assert(!_entityMap.containsKey(entity) || _entityMap[entity] == holder);
      _entityMap[entity] = holder;
    }
  }

  /// Returns a global object for a given [Entity] based on the
  /// [DeferredHolderExpressionKind].
  String kindToHolder(DeferredHolderExpressionKind kind, Entity entity) {
    switch (kind) {
      case DeferredHolderExpressionKind.globalObjectForLibrary:
        return globalObjectForLibrary(entity);
      case DeferredHolderExpressionKind.globalObjectForClass:
        return globalObjectForClass(entity);
      case DeferredHolderExpressionKind.globalObjectForMember:
        return globalObjectForMember(entity);
      case DeferredHolderExpressionKind.globalObjectForConstants:
        return globalObjectForConstants();
      case DeferredHolderExpressionKind.globalObjectForStaticState:
        return globalObjectForStaticState();
    }
    throw UnsupportedError("Unreachable");
  }

  /// Finalizes [DeferredHolderExpression]s [DeferredHolderParameter]s.
  void finalizeReferences() {
    // Finalize [DeferredHolderExpression]s and registers holder usage.
    for (var reference in holderReferences) {
      if (reference.isFinalized) continue;
      Entity entity = reference.entity;
      String holder = kindToHolder(reference.kind, entity);
      js.Expression value = js.VariableUse(holder);
      registerHolderUse(holder, entity);
      reference.value =
          value.withSourceInformation(reference.sourceInformation);
    }

    // Finalize [DeferredHolderParameter]s.
    for (var parameter in holderParameters) {
      if (parameter.isFinalized) continue;
      parameter.name = globalObjectForStaticState();
    }
  }

  /// Registers all of the holders used by a given [DeferredHolderResource].
  void registerHolders(DeferredHolderResource resource) {
    for (var entity in resource.holderCode.keys) {
      var holder = globalObjectForEntity(entity);
      registerHolderUse(holder, entity);
    }
  }

  /// Returns a [List<String>] containing all of the holders except the static
  /// state holder.
  List<String> get nonStaticStateHolders {
    return _holders
        .where((holder) => holder != globalObjectForStaticState())
        .toList(growable: false);
  }

  /// Generates code to declare holders.
  HolderCode declareHolders(DeferredHolderResource resource) {
    // Collect all holders except the static state holder. Then, create a map of
    // holder to list of properties which are associated with that holder, but
    // only with respect to a given [DeferredHolderResource]. Each fragment will
    // have its own [DeferredHolderResource] and associated code.
    Map<String, List<js.Property>> codePerHolder = {};
    final holders = nonStaticStateHolders;
    for (var holder in holders) {
      codePerHolder[holder] = [];
    }

    final holderCode = resource.holderCode;
    holderCode.forEach((entity, properties) {
      assert(_entityMap.containsKey(entity));
      var holder = _entityMap[entity];
      assert(codePerHolder.containsKey(holder));
      codePerHolder[holder].addAll(properties);
    });

    // Create holder initialization code based on the [codePerHolder]. If there
    // are no properties associated with a given holder in this specific
    // [DeferredHolderResource] then it will be omitted. However, in some cases,
    // i.e. the main output unit, we still want to declare the holder with an
    // empty object literal which will be filled in later by another
    // [DeferredHolderResource], i.e. in a specific deferred fragment.
    // The generated code looks like this:
    //
    //    {
    //      var H = {...}, ..., G = {...};
    //      var holders = [ H, ..., G ]; // Main unit only.
    //    }

    List<String> activeHolders = [];
    List<js.VariableInitialization> holderInitializations = [];
    for (var holder in holders) {
      List<js.Property> properties = codePerHolder[holder];
      if (properties.isEmpty) {
        holderInitializations.add(js.VariableInitialization(
            js.VariableDeclaration(holder, allowRename: false),
            resource.initializeEmptyHolders
                ? js.ObjectInitializer(properties)
                : null));
      } else {
        activeHolders.add(holder);
        holderInitializations.add(js.VariableInitialization(
            js.VariableDeclaration(holder, allowRename: false),
            js.ObjectInitializer(properties)));
      }
    }

    List<js.Statement> statements = [];
    statements.add(js.ExpressionStatement(js.VariableDeclarationList(
        holderInitializations,
        indentSplits: false)));
    if (resource.initializeEmptyHolders) {
      statements.add(js.js.statement(
          'var holders = #',
          js.ArrayInitializer(holders
              .map((holder) => js.VariableUse(holder))
              .toList(growable: false))));
    }
    return HolderCode(activeHolders, statements);
  }

  /// Finalizes [resource] to code that updates holders. [resource] must be in
  /// the AST of a deferred fragment.
  void updateHolders(DeferredHolderResource resource) {
    // Declare holders.
    final holderCode = declareHolders(resource);

    // Set names if necessary on deferred holders list.
    js.Expression deferredHoldersList = js.ArrayInitializer(holderCode
        .activeHolders
        .map((holder) => js.js("#", holder))
        .toList(growable: false));
    js.Statement setNames = js.js.statement(
        'hunkHelpers.setFunctionNamesIfNecessary(#deferredHoldersList)',
        {'deferredHoldersList': deferredHoldersList});

    // Update holder assignments.
    final holders = nonStaticStateHolders;
    List<js.Statement> updateHolderAssignments = [setNames];
    for (int i = 0; i < holders.length; i++) {
      var holder = holders[i];
      if (holderCode.activeHolders.contains(holder)) {
        updateHolderAssignments.add(js.js.statement(
            '#holder = hunkHelpers.updateHolder(holdersList[#index], #holder)',
            {'index': js.number(i), 'holder': js.VariableUse(holder)}));
      } else {
        // TODO(sra): Change declaration followed by assignments to declarations
        // with initialization.
        updateHolderAssignments.add(js.js.statement(
            '#holder = holdersList[#index]',
            {'index': js.number(i), 'holder': js.VariableUse(holder)}));
      }
    }

    // Create a single block of all statements.
    List<js.Statement> statements = holderCode.statements
        .followedBy(updateHolderAssignments)
        .toList(growable: false);
    resource.statement = js.Block(statements);
  }

  /// Allocates all [DeferredHolderResource]s and
  /// [DeferredHolderResourceExpression]s.
  void allocateResources() {
    // First ensure all holders used in all [DeferredHolderResource]s have been
    // allocated.
    for (var resource in holderResources) {
      registerHolders(resource);
    }
    _holders.sort();

    // Next finalize all [DeferredHolderResource]s.
    for (var resource in holderResources) {
      switch (resource.kind) {
        case DeferredHolderResourceKind.declaration:
          var holderCode = declareHolders(resource);
          resource.statement = js.Block(holderCode.statements);
          break;
        case DeferredHolderResourceKind.update:
          updateHolders(resource);
          break;
      }
    }
  }

  @override
  void finalize() {
    finalizeReferences();
    allocateResources();
  }

  void _registerDeferredHolderExpression(DeferredHolderExpression node) {
    holderReferences.add(node);
  }

  void _registerDeferredHolderResource(DeferredHolderResource node) {
    holderResources.add(node);
  }

  void _registerDeferredHolderParameter(DeferredHolderParameter node) {
    holderParameters.add(node);
  }
}

/// Scans a JavaScript AST to collect all the [DeferredHolderExpression],
/// [DeferredHolderParameter], [DeferredHolderResource], and
/// [DeferredHolderResourceExpression] nodes.
///
/// The state is kept in the finalizer so that this scan could be extended to
/// look for other deferred expressions in one pass.
class _DeferredHolderExpressionCollectorVisitor extends js.BaseVisitor<void> {
  final DeferredHolderExpressionFinalizerImpl _finalizer;

  _DeferredHolderExpressionCollectorVisitor(this._finalizer);

  @override
  void visitNode(js.Node node) {
    assert(node is! DeferredHolderExpression);
    if (node is js.AstContainer) {
      for (js.Node element in node.containedNodes) {
        element.accept(this);
      }
    } else {
      super.visitNode(node);
    }
  }

  @override
  void visitDeferredExpression(js.DeferredExpression node) {
    if (node is DeferredHolderExpression) {
      _finalizer._registerDeferredHolderExpression(node);
    } else {
      visitNode(node);
    }
  }

  @override
  void visitDeferredStatement(js.DeferredStatement node) {
    if (node is DeferredHolderResource) {
      _finalizer._registerDeferredHolderResource(node);
    } else {
      visitNode(node);
    }
  }

  @override
  void visitParameter(js.Parameter node) {
    if (node is DeferredHolderParameter) {
      _finalizer._registerDeferredHolderParameter(node);
    } else {
      visitNode(node);
    }
  }
}

class HolderCode {
  final List<String> activeHolders;
  final List<js.Statement> statements;
  HolderCode(this.activeHolders, this.statements);
}
