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

library pub.command.serve;

import 'dart:async' hide TimeoutException;

import 'package:barback/barback.dart';

import '../barback/dart_forwarding_transformer.dart';
import '../barback/dart2js_transformer.dart';
import '../barback/pub_package_provider.dart';
import '../barback.dart' as barback;
import '../command.dart';
import '../entrypoint.dart';
import '../exit_codes.dart' as exit_codes;
import '../io.dart';
import '../log.dart' as log;
import '../utils.dart';

final _arrow = getSpecial('\u2192', '=>');

/// Handles the `serve` pub command.
class ServeCommand extends PubCommand {
  String get description => "Run a local web development server.";
  String get usage => "pub serve";

  PubPackageProvider _provider;

  String get hostname => commandOptions['hostname'];

  /// `true` if Dart entrypoints should be compiled to JavaScript.
  bool get useDart2JS => commandOptions['dart2js'];

  /// The build mode.
  BarbackMode get mode => new BarbackMode(commandOptions['mode']);

  ServeCommand() {
    commandParser.addOption('port', defaultsTo: '8080',
        help: 'The port to listen on.');

    // A hidden option for the tests to work around a bug in some of the OS X
    // bots where "localhost" very rarely resolves to the IPv4 loopback address
    // instead of IPv6 (or vice versa). The tests will always set this to
    // 127.0.0.1.
    commandParser.addOption('hostname',
                            defaultsTo: 'localhost',
                            hide: true);
    commandParser.addFlag('dart2js', defaultsTo: true,
        help: 'Compile Dart to JavaScript.');
    commandParser.addFlag('force-poll', defaultsTo: false,
        help: 'Force the use of a polling filesystem watcher.');
    commandParser.addOption('mode', defaultsTo: BarbackMode.DEBUG.toString(),
        help: 'Mode to run transformers in.');
  }

  Future onRun() {
    var port;
    try {
      port = int.parse(commandOptions['port']);
    } on FormatException catch (_) {
      log.error('Could not parse port "${commandOptions['port']}"');
      this.printUsage();
      return flushThenExit(exit_codes.USAGE);
    }

    return entrypoint.ensureLockFileIsUpToDate().then((_) {
      return entrypoint.loadPackageGraph();
    }).then((graph) {
      var builtInTransformers = [new DartForwardingTransformer(mode)];
      if (useDart2JS) {
        builtInTransformers.add(new Dart2JSTransformer(graph, mode));
        // TODO(rnystrom): Add support for dart2dart transformer here.
      }

      var watcherType = commandOptions['force-poll'] ?
          barback.WatcherType.POLLING : barback.WatcherType.AUTO;
      return barback.createServer(hostname, port, graph, mode,
          builtInTransformers: builtInTransformers,
          watcher: watcherType);
    }).then((server) {
      // In release mode, strip out .dart files since all relevant ones have
      // been compiled to JavaScript already.
      if (mode == BarbackMode.RELEASE) {
        server.allowAsset = (url) => !url.path.endsWith(".dart");
      }

      /// This completer is used to keep pub running (by not completing) and
      /// to pipe fatal errors to pub's top-level error-handling machinery.
      var completer = new Completer();

      server.barback.errors.listen((error) {
        log.error(log.red("Build error:\n$error"));
      });

      server.barback.results.listen((result) {
        if (result.succeeded) {
          // TODO(rnystrom): Report using growl/inotify-send where available.
          log.message("Build completed ${log.green('successfully')}");
        } else {
          log.message("Build completed with "
              "${log.red(result.errors.length)} errors.");
        }
      }, onError: (error, [stackTrace]) {
        if (!completer.isCompleted) completer.completeError(error, stackTrace);
      });

      server.results.listen((result) {
        if (result.isSuccess) {
          log.message("${log.green('GET')} ${result.url.path} $_arrow "
              "${result.id}");
          return;
        }

        var msg = "${log.red('GET')} ${result.url.path} $_arrow";
        var error = result.error.toString();
        if (error.contains("\n")) {
          log.message("$msg\n${prefixLines(error)}");
        } else {
          log.message("$msg $error");
        }
      }, onError: (error, [stackTrace]) {
        if (!completer.isCompleted) completer.completeError(error, stackTrace);
      });

      log.message("Serving ${entrypoint.root.name} "
          "on http://$hostname:${server.port}");

      return completer.future;
    });
  }
}
