// Copyright (c) 2012, 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

library event_helper;

import 'dart:async';

abstract class Event {
  void replay(EventSink sink);
}

class DataEvent implements Event {
  final data;

  DataEvent(this.data);

  void replay(EventSink sink) {
    sink.add(data);
  }

  int get hashCode => data.hashCode;

  bool operator ==(Object other) {
    if (other is! DataEvent) return false;
    DataEvent otherEvent = other;
    return data == otherEvent.data;
  }

  String toString() => "DataEvent: $data";
}

class ErrorEvent implements Event {
  final error;

  ErrorEvent(this.error);

  void replay(EventSink sink) {
    sink.addError(error);
  }

  int get hashCode => error.error.hashCode;

  bool operator ==(Object other) {
    if (other is! ErrorEvent) return false;
    ErrorEvent otherEvent = other;
    return error == otherEvent.error;
  }

  String toString() => "ErrorEvent: ${error}";
}

class DoneEvent implements Event {
  const DoneEvent();

  void replay(EventSink sink) {
    sink.close();
  }

  int get hashCode => 42;

  bool operator ==(Object other) => other is DoneEvent;

  String toString() => "DoneEvent";
}

/** Collector of events. */
class Events implements EventSink {
  final List<Event> events = [];
  bool trace = false;
  Completer onDoneSignal = new Completer();

  Events();

  Events.fromIterable(Iterable iterable) {
    for (var value in iterable) add(value);
    close();
  }

  /** Capture events from a stream into a new [Events] object. */
  factory Events.capture(Stream stream, {bool cancelOnError}) = CaptureEvents;

  // EventSink interface.
  void add(var value) {
    if (trace) print("Events#$hashCode: add($value)");
    events.add(new DataEvent(value));
  }

  void addError(error, [StackTrace stackTrace]) {
    if (trace) print("Events#$hashCode: addError($error)");
    events.add(new ErrorEvent(error));
  }

  void close() {
    if (trace) print("Events#$hashCode: close()");
    events.add(const DoneEvent());
    onDoneSignal.complete();
  }

  /**
   * Error shorthand, for writing events manually.
   */
  void error(var value, [StackTrace stackTrace]) {
    addError(value, stackTrace);
  }

  /** Replay the captured events on a sink. */
  void replay(EventSink sink) {
    for (int i = 0; i < events.length; i++) {
      events[i].replay(sink);
    }
  }

  /**
   * Create a new [Events] with the same captured events.
   *
   * This does not copy a subscription.
   */
  Events copy() {
    Events result = new Events();
    replay(result);
    return result;
  }

  // Operations that only work when there is a subscription feeding the Events.

  /**
   * Pauses the subscription that feeds this [Events].
   *
   * Should only be used when there is a subscription. That is, after a
   * call to [subscribeTo].
   */
  void pause([Future resumeSignal]) {
    throw new StateError("Not capturing events.");
  }

  /** Resumes after a call to [pause]. */
  void resume() {
    throw new StateError("Not capturing events.");
  }

  /**
   * Sets an action to be called when this [Events] receives a 'done' event.
   *
   * The action will also be called if capturing events from a stream with
   * `cancelOnError` set to true and receiving an error.
   */
  void onDone(void action()) {
    onDoneSignal.future.whenComplete(action);
  }
}

class CaptureEvents extends Events {
  StreamSubscription subscription;
  bool cancelOnError = false;

  CaptureEvents(Stream stream, {bool cancelOnError: false}) {
    this.cancelOnError = cancelOnError;
    subscription = stream.listen(add,
        onError: addError, onDone: close, cancelOnError: cancelOnError);
  }

  void addError(error, [stackTrace]) {
    super.addError(error, stackTrace);
    if (cancelOnError) {
      onDoneSignal.complete();
    }
  }

  void pause([Future resumeSignal]) {
    if (trace) print("Events#$hashCode: pause");
    subscription.pause(resumeSignal);
  }

  void resume() {
    if (trace) print("Events#$hashCode: resume");
    subscription.resume();
  }

  void onDone(void action()) {
    if (trace) print("Events#$hashCode: onDone");
    super.onDone(action);
  }
}
