// Copyright (c) 2017, 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:kernel/ast.dart';

import '../fasta/problems.dart';

/// Convert '→' to '->' because '→' doesn't show up in some terminals.
/// Remove prefixes that are used very often in tests.
String _shortenInstrumentationString(String s) => s
    .replaceAll('→', '->')
    .replaceAll('dart.core::', '')
    .replaceAll('dart.async::', '')
    .replaceAll('test::', '');

/// Interface providing the ability to record property/value pairs associated
/// with source file locations.  Intended to facilitate testing.
abstract class Instrumentation {
  /// Records a property/value pair associated with the given URI and offset.
  void record(Uri uri, int offset, String property, InstrumentationValue value);
}

/// Interface for values recorded by [Instrumentation].
abstract class InstrumentationValue {
  const InstrumentationValue();

  /// Checks if the given String is an accurate description of this value.
  ///
  /// The default implementation just checks for equality with the return value
  /// of [toString], however derived classes may want a more sophisticated
  /// implementation (e.g. to allow abbreviations in the description).
  ///
  /// Derived classes should ensure that the invariant holds:
  /// `this.matches(this.toString())` should always return `true`.
  bool matches(String description) => description == toString();
}

/// Instance of [InstrumentationValue] describing a forwarding stub.
class InstrumentationValueForForwardingStub extends InstrumentationValue {
  final Procedure procedure;

  InstrumentationValueForForwardingStub(this.procedure);

  @override
  String toString() {
    var buffer = new StringBuffer();
    void writeParameter(VariableDeclaration parameter) {
      var covariances = <String>[];
      if (parameter.isGenericCovariantImpl) {
        covariances.add('genericImpl');
      }
      if (parameter.isCovariant) {
        covariances.add('explicit');
      }
      buffer.write('covariance=(${covariances.join(', ')}) ');
      buffer.write(parameter.type);
      buffer.write(' ');
      buffer.write(parameter.name);
    }

    if (procedure.isAbstract) {
      buffer.write('abstract ');
    }
    var function = procedure.function;
    buffer.write(function.returnType);
    buffer.write(' ');
    switch (procedure.kind) {
      case ProcedureKind.Operator:
        buffer.write('operator');
        break;
      case ProcedureKind.Method:
        break;
      case ProcedureKind.Setter:
        buffer.write('set ');
        break;
      case ProcedureKind.Getter:
        buffer.write('get ');
        break;
      default:
        unhandled('${procedure.kind}', 'InstrumentationValueForForwardingStub',
            -1, null);
        break;
    }
    buffer.write(procedure.name.name);
    if (function.typeParameters.isNotEmpty) {
      buffer.write('<');
      for (int i = 0; i < function.typeParameters.length; i++) {
        if (i != 0) buffer.write(', ');
        var typeParameter = function.typeParameters[i];
        var covariances = <String>[];
        if (typeParameter.isGenericCovariantImpl) {
          covariances.add('genericImpl');
        }
        buffer.write('covariance=(${covariances.join(', ')}) ');
        buffer.write(typeParameter.name);
        buffer.write(' extends ');
        buffer.write(
            new InstrumentationValueForType(typeParameter.bound).toString());
      }
      buffer.write('>');
    }
    buffer.write('(');
    for (int i = 0; i < function.positionalParameters.length; i++) {
      if (i != 0) buffer.write(', ');
      if (i == function.requiredParameterCount) buffer.write('[');
      writeParameter(function.positionalParameters[i]);
    }
    if (function.requiredParameterCount <
        function.positionalParameters.length) {
      buffer.write(']');
    }
    if (function.namedParameters.isNotEmpty) {
      if (function.positionalParameters.length != 0) buffer.write(', ');
      buffer.write('{');
      for (int i = 0; i < function.namedParameters.length; i++) {
        if (i != 0) buffer.write(', ');
        writeParameter(function.namedParameters[i]);
      }
      buffer.write('}');
    }
    buffer.write(')');
    return _shortenInstrumentationString(buffer.toString());
  }
}

/// Instance of [InstrumentationValue] describing a [Member].
class InstrumentationValueForMember extends InstrumentationValue {
  final Member member;

  InstrumentationValueForMember(this.member);

  @override
  String toString() => _shortenInstrumentationString(member.toString());
}

/// Instance of [InstrumentationValue] describing a [DartType].
class InstrumentationValueForType extends InstrumentationValue {
  final DartType type;

  InstrumentationValueForType(this.type);

  @override
  String toString() => _shortenInstrumentationString(type.toString());
}

/// Instance of [InstrumentationValue] describing a list of [DartType]s.
class InstrumentationValueForTypeArgs extends InstrumentationValue {
  final List<DartType> types;

  InstrumentationValueForTypeArgs(this.types);

  @override
  String toString() => types
      .map((type) => new InstrumentationValueForType(type).toString())
      .join(', ');
}

/// Instance of [InstrumentationValue] which only matches the given literal
/// string.
class InstrumentationValueLiteral extends InstrumentationValue {
  final String value;

  const InstrumentationValueLiteral(this.value);

  @override
  String toString() => value;
}
