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

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 noArgs = CallStructure._(0);
  static const CallStructure oneArg = CallStructure._(1);
  static const CallStructure twoArgs = CallStructure._(2);

  static const List<List<CallStructure>> _common = [
    [noArgs, CallStructure._(0, 1), CallStructure._(0, 2)],
    [oneArg, CallStructure._(1, 1), CallStructure._(1, 2)],
    [twoArgs, 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 argumentCount == other.argumentCount &&
        namedArgumentCount == other.namedArgumentCount &&
        typeArgumentCount == other.typeArgumentCount &&
        _sameNames(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();
  }
}
