// 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 'dart:convert';

import 'package:meta/meta.dart';

import 'codecs.dart';
import 'common.dart';
import 'errors.dart';
import 'proxy.dart';

typedef bool _InvocationMatcher(Map<String, dynamic> entry);

/// Used to record the order in which invocations were replayed.
///
/// Tests can later check expectations about the order in which invocations
/// were replayed vis-a-vis the order in which they were recorded.
int _nextOrdinal = 0;

/// Mixin that enables replaying of property accesses, property mutations, and
/// method invocations from a prior recording.
///
/// This class uses `noSuchMethod` to replay a well-defined set of invocations
/// (including property gets and sets) on an object. Subclasses wire this up by
/// doing the following:
///
///   - Populate the list of method invocations to replay in the [methods] map.
///   - Populate the list of property invocations to replay in the [properties]
///     map. The symbol name for getters should be the property name, and the
///     symbol name for setters should be the property name immediately
///     followed by an equals sign (e.g. `propertyName=`).
///   - Do not implement a concrete getter, setter, or method that you wish to
///     replay, as doing so will circumvent the machinery that this mixin uses
///     (`noSuchMethod`) to replay invocations.
///
/// **Example use**:
///
///     abstract class Foo {
///       ComplexObject sampleMethod();
///
///       Foo sampleParent;
///     }
///
///     class ReplayFoo extends ReplayProxyMixin implements Foo {
///       final List<Map<String, dynamic>> manifest;
///       final String identifier;
///
///       ReplayFoo(this.manifest, this.identifier) {
///         methods.addAll(<Symbol, Converter<dynamic, dynamic>>{
///           #sampleMethod: complexObjectReviver,
///         });
///
///         properties.addAll(<Symbol, Converter<dynamic, dynamic>>{
///           #sampleParent: fooReviver,
///           const Symbol('sampleParent='): passthroughReviver,
///         });
///       }
///     }
abstract class ReplayProxyMixin implements ProxyObject, ReplayAware {
  /// Maps method names to [Converter]s that will revive result values.
  ///
  /// Invocations of methods listed in this map will be replayed by looking for
  /// matching invocations in the [manifest] and reviving the invocation return
  /// value using the [Converter] found in this map.
  @protected
  final Map<Symbol, Converter<dynamic, dynamic>> methods =
      <Symbol, Converter<dynamic, dynamic>>{};

  /// Maps property getter and setter names to [Converter]s that will revive
  /// result values.
  ///
  /// Access and mutation of properties listed in this map will be replayed
  /// by looking for matching property accesses in the [manifest] and reviving
  /// the invocation return value using the [Converter] found in this map.
  ///
  /// The keys for property getters are the simple property names, whereas the
  /// keys for property setters are the property names followed by an equals
  /// sign (e.g. `propertyName=`).
  @protected
  final Map<Symbol, Converter<dynamic, dynamic>> properties =
      <Symbol, Converter<dynamic, dynamic>>{};

  /// The manifest of recorded invocation events.
  ///
  /// When invocations are received on this object, we will attempt find a
  /// matching invocation in this manifest to perform the replay. If no such
  /// invocation is found (or if it has already been replayed), the caller will
  /// receive a [NoMatchingInvocationError].
  ///
  /// This manifest exists as `MANIFEST.txt` in a recording directory.
  @protected
  List<Map<String, dynamic>> get manifest;

  /// Protected method for subclasses to be notified when an invocation has
  /// been successfully replayed, and the result is about to be returned to
  /// the caller.
  ///
  /// Returns the value that is to be returned to the caller. The default
  /// implementation returns [result] (replayed from the recording); subclasses
  /// may override this method to alter the result that's returned to the
  /// caller.
  @protected
  dynamic onResult(Invocation invocation, dynamic result) => result;

  @override
  dynamic noSuchMethod(Invocation invocation) {
    Symbol name = invocation.memberName;
    Converter<dynamic, dynamic> reviver =
        invocation.isAccessor ? properties[name] : methods[name];

    if (reviver == null) {
      // No reviver generally means that there truly is no such method on
      // this object. The exception is when the invocation represents a getter
      // on a method, in which case we return a method proxy that, when
      // invoked, will replay the desired invocation.
      return invocation.isGetter && methods[name] != null
          ? new MethodProxy(this, name)
          : super.noSuchMethod(invocation);
    }

    Map<String, dynamic> entry = _nextEvent(invocation);
    if (entry == null) {
      throw new NoMatchingInvocationError(invocation);
    }
    entry[kManifestOrdinalKey] = _nextOrdinal++;

    dynamic error = entry[kManifestErrorKey];
    if (error != null) {
      throw const ToError().convert(error);
    }
    dynamic result = reviver.convert(entry[kManifestResultKey]);
    result = onResult(invocation, result);
    return result;
  }

  /// Finds the next available invocation event in the [manifest] that matches
  /// the specified [invocation].
  Map<String, dynamic> _nextEvent(Invocation invocation) {
    _InvocationMatcher matches = _getMatcher(invocation);
    return manifest.firstWhere((Map<String, dynamic> entry) {
      return entry[kManifestOrdinalKey] == null && matches(entry);
    }, orElse: () => null);
  }

  _InvocationMatcher _getMatcher(Invocation invocation) {
    String name = getSymbolName(invocation.memberName);
    List<dynamic> args = encode(invocation.positionalArguments);
    Map<String, dynamic> namedArgs = encode(invocation.namedArguments);

    if (invocation.isGetter) {
      return (Map<String, dynamic> entry) =>
          entry[kManifestTypeKey] == kGetType &&
          entry[kManifestPropertyKey] == name &&
          entry[kManifestObjectKey] == identifier;
    } else if (invocation.isSetter) {
      return (Map<String, dynamic> entry) =>
          entry[kManifestTypeKey] == kSetType &&
          entry[kManifestPropertyKey] == name &&
          deeplyEqual(entry[kManifestValueKey], args[0]) &&
          entry[kManifestObjectKey] == identifier;
    } else {
      return (Map<String, dynamic> entry) {
        return entry[kManifestTypeKey] == kInvokeType &&
            entry[kManifestMethodKey] == name &&
            deeplyEqual(entry[kManifestPositionalArgumentsKey], args) &&
            deeplyEqual(_asNamedArgsType(entry[kManifestNamedArgumentsKey]),
                namedArgs) &&
            entry[kManifestObjectKey] == identifier;
      };
    }
  }

  static Map<String, dynamic> _asNamedArgsType(Map<dynamic, dynamic> map) {
    return new Map<String, dynamic>.from(map);
  }
}
