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