// 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:async';
import 'package:file/file.dart';
import 'package:file/src/backends/memory/node.dart';

import 'package:meta/meta.dart';

import 'common.dart';
import 'events.dart';
import 'mutable_recording.dart';
import 'proxy.dart';
import 'result_reference.dart';

/// Mixin that enables recording of property accesses, property mutations, and
/// method invocations.
///
/// This class uses `noSuchMethod` to record a well-defined set of invocations
/// (including property gets and sets) on an object before passing the
/// invocation on to a delegate. Subclasses wire this up by doing the following:
///
///   - Populate the list of method invocations to record in the [methods] map.
///   - Populate the list of property invocations to record 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
///     record, as doing so will circumvent the machinery that this mixin uses
///     (`noSuchMethod`) to record invocations.
///
/// **Example use**:
///
///     abstract class Foo {
///       void sampleMethod();
///
///       int sampleProperty;
///     }
///
///     class RecordingFoo extends RecordingProxyMixin implements Foo {
///       final Foo delegate;
///
///       RecordingFoo(this.delegate) {
///         methods.addAll(<Symbol, Function>{
///           #sampleMethod: delegate.sampleMethod,
///         });
///
///         properties.addAll(<Symbol, Function>{
///           #sampleProperty: () => delegate.sampleProperty,
///           const Symbol('sampleProperty='): (int value) {
///             delegate.sampleProperty = value;
///           },
///         });
///       }
///     }
///
/// **Behavioral notes**:
///
/// Methods that return [Future]s will not be recorded until the future
/// completes.
///
/// Methods that return [Stream]s will be recorded immediately, but their
/// return values will be recorded as a [List] that will grow as the stream
/// produces data.
mixin RecordingProxyMixin on Object implements ProxyObject, ReplayAware {
  /// Maps method names to delegate functions.
  ///
  /// Invocations of methods listed in this map will be recorded after
  /// invoking the underlying delegate function.
  @protected
  final Map<Symbol, Function> methods = <Symbol, Function>{};

  /// Maps property getter and setter names to delegate functions.
  ///
  /// Access and mutation of properties listed in this map will be recorded
  /// after invoking the underlying delegate function.
  ///
  /// 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, Function> properties = <Symbol, Function>{};

  /// The object to which invocation events will be recorded.
  @protected
  MutableRecording get recording;

  /// The stopwatch used to record invocation timestamps.
  @protected
  Stopwatch get stopwatch;

  /// Handles invocations for which there is no concrete implementation
  /// function.
  ///
  /// For invocations that have matching entries in [methods] (for method
  /// invocations) or [properties] (for property access and mutation), this
  /// will record the invocation in [recording] after invoking the underlying
  /// delegate method. All other invocations will throw a [NoSuchMethodError].
  @override
  dynamic noSuchMethod(Invocation invocation) {
    Symbol name = invocation.memberName;
    List<dynamic> args = invocation.positionalArguments;
    Map<Symbol, dynamic> namedArgs = invocation.namedArguments;
    Function method = invocation.isAccessor ? properties[name] : methods[name];
    int time = stopwatch.elapsedMilliseconds;

    if (method == null) {
      // No delegate function 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 perform the desired recording.
      return invocation.isGetter && methods[name] != null
          ? MethodProxy(this, name)
          : super.noSuchMethod(invocation);
    }

    InvocationEvent<dynamic> createEvent({dynamic result, dynamic error}) {
      if (invocation.isGetter) {
        return LivePropertyGetEvent<dynamic>(this, name, result, error, time);
      } else if (invocation.isSetter) {
        return LivePropertySetEvent<dynamic>(this, name, args[0], error, time);
      } else {
        return LiveMethodEvent<dynamic>(
            this, name, args, namedArgs, result, error, time);
      }
    }

    // Invoke the configured delegate method, recording an error if one occurs.
    dynamic value;
    try {
      value = Function.apply(method, args, namedArgs);
    } catch (error) {
      recording.add(createEvent(error: error) as LiveInvocationEvent<dynamic>);
      rethrow;
    }

    // Wrap Future and Stream results so that we record their values as they
    // become available.
    // We have to instantiate the correct type of StreamReference or
    // FutureReference, so that types are not lost when we unwrap the references
    // afterward.
    if (value is Stream<FileSystemEntity>) {
      value =
          StreamReference<FileSystemEntity>(value as Stream<FileSystemEntity>);
    } else if (value is Stream<String>) {
      value = StreamReference<String>(value as Stream<String>);
    } else if (value is Stream) {
      throw UnimplementedError(
          'Cannot record method with return type ${value.runtimeType}');
    } else if (value is Future<bool>) {
      value = FutureReference<bool>(value as Future<bool>);
    } else if (value is Future<Directory>) {
      value = FutureReference<Directory>(value as Future<Directory>);
    } else if (value is Future<File>) {
      value = FutureReference<File>(value as Future<File>);
    } else if (value is Future<FileNode>) {
      value = FutureReference<FileNode>(value as Future<FileNode>);
    } else if (value is Future<FileStat>) {
      value = FutureReference<FileStat>(value as Future<FileStat>);
    } else if (value is Future<Link>) {
      value = FutureReference<Link>(value as Future<Link>);
    } else if (value is Future<FileSystemEntity>) {
      value =
          FutureReference<FileSystemEntity>(value as Future<FileSystemEntity>);
    } else if (value is Future<FileSystemEntityType>) {
      value = FutureReference<FileSystemEntityType>(
          value as Future<FileSystemEntityType>);
    } else if (value is Future<String>) {
      value = FutureReference<String>(value as Future<String>);
    } else if (value is Future<RandomAccessFile>) {
      value =
          FutureReference<RandomAccessFile>(value as Future<RandomAccessFile>);
    } else if (value is Future<void>) {
      value = FutureReference<void>(value as Future<void>);
    }

    // Record the invocation event associated with this invocation.
    recording.add(createEvent(result: value) as LiveInvocationEvent<dynamic>);

    // Unwrap any result references before returning to the caller.
    dynamic result = value;
    while (result is ResultReference) {
      result = result.value;
    }
    return result;
  }
}
