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

import '../common/names.dart' show Names;
import '../elements/entities.dart' show ParameterStructure;
import '../serialization/serialization.dart';
import '../util/util.dart';
import 'selector.dart' show Selector;

/// The structure of the arguments at a call-site.
///
/// A call-site passes some number of arguments: some positional arguments
/// followed by some named arguments. There may also be type arguments.
///
/// A CallStructure is unmodifiable.

// TODO(johnniwinther): Should isGetter/isSetter be part of the call structure
// instead of the selector?
class CallStructure {
  /// Tag used for identifying serialized [CallStructure] objects in a debugging
  /// data stream.
  static const String tag = 'call-structure';

  static const CallStructure NO_ARGS = CallStructure._(0);
  static const CallStructure ONE_ARG = CallStructure._(1);
  static const CallStructure TWO_ARGS = CallStructure._(2);

  static const List<List<CallStructure>> _common = [
    [NO_ARGS, CallStructure._(0, 1), CallStructure._(0, 2)],
    [ONE_ARG, CallStructure._(1, 1), CallStructure._(1, 2)],
    [TWO_ARGS, CallStructure._(2, 1), CallStructure._(2, 2)],
    [CallStructure._(3), CallStructure._(3, 1), CallStructure._(3, 2)],
    [CallStructure._(4), CallStructure._(4, 1), CallStructure._(4, 2)],
    [CallStructure._(5), CallStructure._(5, 1), CallStructure._(5, 2)],
    [CallStructure._(6)],
    [CallStructure._(7)],
    [CallStructure._(8)],
    [CallStructure._(9)],
    [CallStructure._(10)],
  ];

  /// The number of type arguments of the call.
  final int typeArgumentCount;

  /// The numbers of arguments of the call. Includes named arguments.
  final int argumentCount;

  /// The number of named arguments of the call.
  int get namedArgumentCount => 0;

  /// The number of positional argument of the call.
  int get positionalArgumentCount => argumentCount;

  const CallStructure._(this.argumentCount, [this.typeArgumentCount = 0]);

  factory CallStructure.unnamed(int argumentCount,
      [int typeArgumentCount = 0]) {
    // This simple canonicalization of common call structures greatly reduces
    // the number of allocations of CallStructure objects.
    if (argumentCount < _common.length) {
      final row = _common[argumentCount];
      if (typeArgumentCount < row.length) {
        final result = row[typeArgumentCount];
        assert(result.argumentCount == argumentCount &&
            result.typeArgumentCount == typeArgumentCount);
        return result;
      }
    }
    return CallStructure._(argumentCount, typeArgumentCount);
  }

  factory CallStructure(int argumentCount,
      [List<String> namedArguments, int typeArgumentCount = 0]) {
    if (namedArguments == null || namedArguments.isEmpty) {
      return CallStructure.unnamed(argumentCount, typeArgumentCount);
    }
    return _NamedCallStructure(
        argumentCount, namedArguments, typeArgumentCount, null);
  }

  /// Deserializes a [CallStructure] object from [source].
  factory CallStructure.readFromDataSource(DataSourceReader source) {
    source.begin(tag);
    int argumentCount = source.readInt();
    List<String> namedArguments = source.readStrings();
    int typeArgumentCount = source.readInt();
    source.end(tag);
    return CallStructure(argumentCount, namedArguments, typeArgumentCount);
  }

  /// Serializes this [CallStructure] to [sink].
  void writeToDataSink(DataSinkWriter sink) {
    sink.begin(tag);
    sink.writeInt(argumentCount);
    sink.writeStrings(namedArguments);
    sink.writeInt(typeArgumentCount);
    sink.end(tag);
  }

  /// Returns `true` if this call structure is normalized, that is, its named
  /// arguments are sorted.
  bool get isNormalized => true;

  /// Returns the normalized version of this call structure.
  ///
  /// A [CallStructure] is normalized if its named arguments are sorted.
  CallStructure toNormalized() => this;

  CallStructure withTypeArgumentCount(int typeArgumentCount) =>
      CallStructure(argumentCount, namedArguments, typeArgumentCount);

  /// `true` if this call has named arguments.
  bool get isNamed => false;

  /// `true` if this call has no named arguments.
  bool get isUnnamed => true;

  /// The names of the named arguments in call-site order.
  List<String> get namedArguments => const [];

  /// The names of the named arguments in canonicalized order.
  List<String> getOrderedNamedArguments() => const [];

  CallStructure get nonGeneric => typeArgumentCount == 0
      ? this
      : CallStructure(argumentCount, namedArguments);

  /// Short textual representation use for testing.
  String get shortText {
    StringBuffer sb = StringBuffer();
    sb.write('(');
    sb.write(positionalArgumentCount);
    if (namedArgumentCount > 0) {
      sb.write(',');
      sb.write(getOrderedNamedArguments().join(','));
    }
    sb.write(')');
    return sb.toString();
  }

  /// A description of the argument structure.
  String structureToString() {
    StringBuffer sb = StringBuffer();
    sb.write('arity=$argumentCount');
    if (typeArgumentCount != 0) {
      sb.write(', types=$typeArgumentCount');
    }
    return sb.toString();
  }

  @override
  String toString() => 'CallStructure(${structureToString()})';

  Selector get callSelector => Selector.call(Names.call, this);

  bool match(CallStructure other) {
    if (identical(this, other)) return true;
    return this.argumentCount == other.argumentCount &&
        this.namedArgumentCount == other.namedArgumentCount &&
        this.typeArgumentCount == other.typeArgumentCount &&
        _sameNames(this.namedArguments, other.namedArguments);
  }

  // TODO(johnniwinther): Cache hash code?
  @override
  int get hashCode {
    return Hashing.listHash(
        namedArguments,
        Hashing.objectHash(argumentCount,
            Hashing.objectHash(typeArgumentCount, namedArguments.length)));
  }

  @override
  bool operator ==(other) {
    if (other is! CallStructure) return false;
    return match(other);
  }

  bool signatureApplies(ParameterStructure parameters) {
    int requiredParameterCount = parameters.requiredPositionalParameters;
    int optionalParameterCount = parameters.optionalParameters;
    int parameterCount = parameters.totalParameters;
    if (argumentCount > parameterCount) return false;
    if (positionalArgumentCount < requiredParameterCount) return false;
    if (typeArgumentCount != 0) {
      if (typeArgumentCount != parameters.typeParameters) return false;
    }

    if (parameters.namedParameters.isEmpty) {
      // We have already checked that the number of arguments are
      // not greater than the number of parameters. Therefore the
      // number of positional arguments are not greater than the
      // number of parameters.
      assert(positionalArgumentCount <= parameterCount);
      return namedArguments.isEmpty;
    } else {
      if (positionalArgumentCount > requiredParameterCount) return false;
      assert(positionalArgumentCount == requiredParameterCount);
      if (namedArgumentCount >
          optionalParameterCount + parameters.requiredNamedParameters.length)
        return false;

      int nameIndex = 0;
      List<String> namedParameters = parameters.namedParameters;
      int seenRequiredNamedParameters = 0;

      for (String name in getOrderedNamedArguments()) {
        bool found = false;
        // Note: we start at the existing index because arguments are sorted.
        while (nameIndex < namedParameters.length) {
          String parameterName = namedParameters[nameIndex];
          if (name == parameterName) {
            if (parameters.requiredNamedParameters.contains(name))
              seenRequiredNamedParameters++;
            found = true;
            break;
          }
          nameIndex++;
        }
        if (!found) return false;
      }
      return seenRequiredNamedParameters ==
          parameters.requiredNamedParameters.length;
    }
  }

  static bool _sameNames(List<String> first, List<String> second) {
    assert(first.length == second.length);
    for (int i = 0; i < first.length; i++) {
      if (first[i] != second[i]) return false;
    }
    return true;
  }
}

/// Call structure with named arguments. This is an implementation detail of the
/// CallStructure interface.
class _NamedCallStructure extends CallStructure {
  @override
  final List<String> namedArguments;

  /// The list of ordered named arguments is computed lazily. Initially `null`.
  List<String> /*?*/ _orderedNamedArguments;

  _NamedCallStructure(int argumentCount, this.namedArguments,
      int typeArgumentCount, this._orderedNamedArguments)
      : assert(namedArguments.isNotEmpty),
        super._(argumentCount, typeArgumentCount);

  @override
  bool get isNamed => true;

  @override
  bool get isUnnamed => false;

  @override
  int get namedArgumentCount => namedArguments.length;

  @override
  int get positionalArgumentCount => argumentCount - namedArgumentCount;

  @override
  bool get isNormalized =>
      identical(namedArguments, getOrderedNamedArguments());

  @override
  CallStructure toNormalized() => isNormalized
      ? this
      : _NamedCallStructure(argumentCount, getOrderedNamedArguments(),
          typeArgumentCount, getOrderedNamedArguments());

  @override
  List<String> getOrderedNamedArguments() {
    return _orderedNamedArguments ??= _getOrderedNamedArguments();
  }

  List<String> _getOrderedNamedArguments() {
    List<String> ordered = List.of(namedArguments, growable: false);
    ordered.sort((String first, String second) => first.compareTo(second));
    // Use the same List if [namedArguments] is already ordered to indicate this
    // _NamedCallStructure is normalized.
    if (CallStructure._sameNames(ordered, namedArguments)) {
      return namedArguments;
    }
    return ordered;
  }

  @override
  String structureToString() {
    StringBuffer sb = StringBuffer();
    sb.write('arity=$argumentCount, named=[${namedArguments.join(', ')}]');
    if (typeArgumentCount != 0) {
      sb.write(', types=$typeArgumentCount');
    }
    return sb.toString();
  }
}
