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

// @dart = 2.9

import 'dart:convert';

import "package:expect/expect.dart";

/// Helper class for determining when no argument is passed to a function.
class Absent {
  const Absent();
}

const absent = Absent();

/// Returns an approximate representation of the syntax that was used to
/// construct [x].  Extra parentheses are used around unary and binary
/// expressions to disambiguate precedence.
String syntax(Object x) {
  var knownSyntax = SyntaxTracker.known[x];
  if (knownSyntax != null) return knownSyntax;
  if (x is SyntaxTracker || x is num) {
    return x.toString();
  } else if (x is List) {
    return '[${x.map(syntax).join(', ')}]';
  } else if (x is Set) {
    if (x.isEmpty) return 'Set()';
    return '{${x.map(syntax).join(', ')}}';
  } else if (x is Map) {
    if (x.isEmpty) return '{}';
    var entries = x.entries
        .map((entry) => '${syntax(entry.key)}: ${syntax(entry.value)}');
    return '{ ${entries.join(', ')} }';
  } else if (x is String) {
    return json.encode(x);
  } else {
    throw UnimplementedError('Unknown syntax for $x.  '
        'Consider adding to `SyntaxTracker.known`.');
  }
}

/// Instances of this class record the syntax of operations performed on them.
class SyntaxTracker {
  final String _syntax;

  SyntaxTracker(this._syntax);

  String toString() => _syntax;

  static String args([Object x = absent, Object y = absent]) =>
      '(${[x, y].where((v) => v is! Absent).join(', ')})';

  static String typeArgs(Type T, Type U) =>
      T == dynamic && U == dynamic ? '' : '<${syntax(T)}, ${syntax(U)}>';

  /// Simple objects with known syntactic representations.  Tests can add to
  /// this map.
  static Map<Object, String> known = {
    true: 'true',
    false: 'false',
    null: 'null'
  };
}

/// Extension allowing us to detect the syntax of most operations performed on
/// arbitrary types.
extension SyntaxTrackingExtension on Object {
  Object method<T, U>([Object x = absent, Object y = absent]) => SyntaxTracker(
      '${syntax(this)}.method${SyntaxTracker.typeArgs(T, U)}${SyntaxTracker.args(x, y)}');

  Object call<T, U>([Object x = absent, Object y = absent]) => SyntaxTracker(
      '${syntax(this)}${SyntaxTracker.typeArgs(T, U)}${SyntaxTracker.args(x, y)}');

  Object get getter => SyntaxTracker('${syntax(this)}.getter');

  Object operator [](Object index) =>
      SyntaxTracker('${syntax(this)}[${syntax(index)}]');

  Object operator -() => SyntaxTracker('(-${syntax(this)})');

  Object operator ~() => SyntaxTracker('(~${syntax(this)})');

  Object operator *(Object other) =>
      SyntaxTracker('(${syntax(this)} * ${syntax(other)})');

  Object operator /(Object other) =>
      SyntaxTracker('(${syntax(this)} / ${syntax(other)})');

  Object operator ~/(Object other) =>
      SyntaxTracker('(${syntax(this)} ~/ ${syntax(other)})');

  Object operator %(Object other) =>
      SyntaxTracker('(${syntax(this)} % ${syntax(other)})');

  Object operator +(Object other) =>
      SyntaxTracker('(${syntax(this)} + ${syntax(other)})');

  Object operator -(Object other) =>
      SyntaxTracker('(${syntax(this)} - ${syntax(other)})');

  Object operator <<(Object other) =>
      SyntaxTracker('(${syntax(this)} << ${syntax(other)})');

  Object operator >>(Object other) =>
      SyntaxTracker('(${syntax(this)} >> ${syntax(other)})');

  Object operator &(Object other) =>
      SyntaxTracker('(${syntax(this)} & ${syntax(other)})');

  Object operator ^(Object other) =>
      SyntaxTracker('(${syntax(this)} ^ ${syntax(other)})');

  Object operator |(Object other) =>
      SyntaxTracker('(${syntax(this)} | ${syntax(other)})');

  Object operator <(Object other) =>
      SyntaxTracker('(${syntax(this)} < ${syntax(other)})');

  Object operator >(Object other) =>
      SyntaxTracker('(${syntax(this)} > ${syntax(other)})');

  Object operator <=(Object other) =>
      SyntaxTracker('(${syntax(this)} <= ${syntax(other)})');

  Object operator >=(Object other) =>
      SyntaxTracker('(${syntax(this)} >= ${syntax(other)})');
}

void checkSyntax(Object x, String expectedSyntax) {
  Expect.equals(expectedSyntax, syntax(x));
}

Object f<T, U>([Object x = absent, Object y = absent]) => SyntaxTracker(
    'f${SyntaxTracker.typeArgs(T, U)}${SyntaxTracker.args(x, y)}');

Object x = SyntaxTracker('x');
