// Copyright (c) 2016, 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:stream_channel/stream_channel.dart';
import 'package:term_glyph/term_glyph.dart' as glyph;

import '../backend/declarer.dart';
import '../backend/group.dart';
import '../backend/live_test.dart';
import '../backend/metadata.dart';
import '../backend/operating_system.dart';
import '../backend/suite.dart';
import '../backend/test.dart';
import '../backend/test_platform.dart';
import '../util/remote_exception.dart';
import '../utils.dart';

class RemoteListener {
  /// The test suite to run.
  final Suite _suite;

  /// The zone to forward prints to, or `null` if prints shouldn't be forwarded.
  final Zone _printZone;

  /// Extracts metadata about all the tests in the function returned by
  /// [getMain] and returns a channel that will send information about them.
  ///
  /// The main function is wrapped in a closure so that we can handle it being
  /// undefined here rather than in the generated code.
  ///
  /// Once that's done, this starts listening for commands about which tests to
  /// run.
  ///
  /// If [hidePrints] is `true` (the default), calls to `print()` within this
  /// suite will not be forwarded to the parent zone's print handler. However,
  /// the caller may want them to be forwarded in (for example) a browser
  /// context where they'll be visible in the development console.
  static StreamChannel start(AsyncFunction getMain(), {bool hidePrints: true}) {
    // This has to be synchronous to work around sdk#25745. Otherwise, there'll
    // be an asynchronous pause before a syntax error notification is sent,
    // which will cause the send to fail entirely.
    var controller =
        new StreamChannelController(allowForeignErrors: false, sync: true);
    var channel = new MultiChannel(controller.local);

    var printZone = hidePrints ? null : Zone.current;
    runZoned(() async {
      var main;
      try {
        main = getMain();
      } on NoSuchMethodError catch (_) {
        _sendLoadException(channel, "No top-level main() function defined.");
        return;
      } catch (error, stackTrace) {
        _sendError(channel, error, stackTrace);
        return;
      }

      if (main is! Function) {
        _sendLoadException(channel, "Top-level main getter is not a function.");
        return;
      } else if (main is! AsyncFunction) {
        _sendLoadException(
            channel, "Top-level main() function takes arguments.");
        return;
      }

      var message = await channel.stream.first;

      if (message['asciiGlyphs'] ?? false) glyph.ascii = true;
      var metadata = new Metadata.deserialize(message['metadata']);
      var declarer = new Declarer(
          metadata: metadata,
          collectTraces: message['collectTraces'],
          noRetry: message['noRetry']);
      await declarer.declare(main);

      var os =
          message['os'] == null ? null : OperatingSystem.find(message['os']);
      var platform = TestPlatform.find(message['platform']);
      var suite = new Suite(declarer.build(),
          platform: platform, os: os, path: message['path']);
      new RemoteListener._(suite, printZone)._listen(channel);
    }, onError: (error, stackTrace) {
      _sendError(channel, error, stackTrace);
    }, zoneSpecification: new ZoneSpecification(print: (_, __, ___, line) {
      if (printZone != null) printZone.print(line);
      channel.sink.add({"type": "print", "line": line});
    }));

    return controller.foreign;
  }

  /// Sends a message over [channel] indicating that the tests failed to load.
  ///
  /// [message] should describe the failure.
  static void _sendLoadException(StreamChannel channel, String message) {
    channel.sink.add({"type": "loadException", "message": message});
  }

  /// Sends a message over [channel] indicating an error from user code.
  static void _sendError(StreamChannel channel, error, StackTrace stackTrace) {
    channel.sink.add({
      "type": "error",
      "error": RemoteException.serialize(error, stackTrace)
    });
  }

  RemoteListener._(this._suite, this._printZone);

  /// Send information about [_suite] across [channel] and start listening for
  /// commands to run the tests.
  void _listen(MultiChannel channel) {
    channel.sink.add({
      "type": "success",
      "root": _serializeGroup(channel, _suite.group, [])
    });
  }

  /// Serializes [group] into a JSON-safe map.
  ///
  /// [parents] lists the groups that contain [group].
  Map _serializeGroup(
      MultiChannel channel, Group group, Iterable<Group> parents) {
    parents = parents.toList()..add(group);
    return {
      "type": "group",
      "name": group.name,
      "metadata": group.metadata.serialize(),
      "trace": group.trace?.toString(),
      "setUpAll": _serializeTest(channel, group.setUpAll, parents),
      "tearDownAll": _serializeTest(channel, group.tearDownAll, parents),
      "entries": group.entries.map((entry) {
        return entry is Group
            ? _serializeGroup(channel, entry, parents)
            : _serializeTest(channel, entry, parents);
      }).toList()
    };
  }

  /// Serializes [test] into a JSON-safe map.
  ///
  /// [groups] lists the groups that contain [test]. Returns `null` if [test]
  /// is `null`.
  Map _serializeTest(MultiChannel channel, Test test, Iterable<Group> groups) {
    if (test == null) return null;

    var testChannel = channel.virtualChannel();
    testChannel.stream.listen((message) {
      assert(message['command'] == 'run');
      _runLiveTest(test.load(_suite, groups: groups),
          channel.virtualChannel(message['channel']));
    });

    return {
      "type": "test",
      "name": test.name,
      "metadata": test.metadata.serialize(),
      "trace": test.trace?.toString(),
      "channel": testChannel.id
    };
  }

  /// Runs [liveTest] and sends the results across [channel].
  void _runLiveTest(LiveTest liveTest, MultiChannel channel) {
    channel.stream.listen((message) {
      assert(message['command'] == 'close');
      liveTest.close();
    });

    liveTest.onStateChange.listen((state) {
      channel.sink.add({
        "type": "state-change",
        "status": state.status.name,
        "result": state.result.name
      });
    });

    liveTest.onError.listen((asyncError) {
      channel.sink.add({
        "type": "error",
        "error":
            RemoteException.serialize(asyncError.error, asyncError.stackTrace)
      });
    });

    liveTest.onMessage.listen((message) {
      if (_printZone != null) _printZone.print(message.text);
      channel.sink.add({
        "type": "message",
        "message-type": message.type.name,
        "text": message.text
      });
    });

    runZoned(() {
      liveTest.run().then((_) => channel.sink.add({"type": "complete"}));
    }, zoneValues: {#test.runner.test_channel: channel});
  }
}
