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

/// A tool to gather coverage data from an app generated with dart2js. This
/// depends on code that has been landed in the bleeding_edge version of dart2js
/// and that we expect to become publicly visible in version 0.13.0 of the Dart
/// SDK).
///
/// This tool starts a server that answers to mainly 2 requests:
///    * a GET request to retrieve the application
///    * POST requests to record coverage data.
///
/// It is intended to be used as follows:
///    * generate an app by running dart2js with the environment value
///      -DtraceCalls=post provided to the vm, and the --dump-info
///      flag provided to dart2js.
///    * start this server, and proxy requests from your normal frontend
///      server to this one.
library dart2js_info.bin.coverage_log_server;

import 'dart:async';
import 'dart:convert';
import 'dart:io';

import 'package:args/args.dart';
import 'package:path/path.dart' as path;
import 'package:shelf/shelf.dart' as shelf;
import 'package:shelf/shelf_io.dart' as shelf;

const _DEFAULT_OUT_TEMPLATE = '<dart2js-out-file>.coverage.json';

main(List<String> argv) async {
  var parser = new ArgParser()
    ..addOption('port', abbr: 'p', help: 'port number', defaultsTo: "8080")
    ..addOption('host',
        help: 'host name (use 0.0.0.0 for all interfaces)',
        defaultsTo: 'localhost')
    ..addFlag('help',
        abbr: 'h', help: 'show this help message', negatable: false)
    ..addOption('uri-prefix',
        help: 'uri path prefix that will hit this server. This will be injected'
            ' into the .js file',
        defaultsTo: '')
    ..addOption('out',
        abbr: 'o', help: 'output log file', defaultsTo: _DEFAULT_OUT_TEMPLATE);
  var args = parser.parse(argv);
  if (args['help'] == true || args.rest.isEmpty) {
    print('usage: dart coverage_logging.dart [options] '
        '<dart2js-out-file> [<html-file>]');
    print(parser.usage);
    exit(1);
  }

  var jsPath = args.rest[0];
  var htmlPath = null;
  if (args.rest.length > 1) {
    htmlPath = args.rest[1];
  }
  var outPath = args['out'];
  if (outPath == _DEFAULT_OUT_TEMPLATE) outPath = '$jsPath.coverage.json';
  var server = new _Server(args['host'], int.parse(args['port']), jsPath,
      htmlPath, outPath, args['uri-prefix']);
  await server.run();
}

class _Server {
  /// Server hostname, typically `localhost`,  but can be `0.0.0.0`.
  final String hostname;

  /// Port the server will listen to.
  final int port;

  /// JS file (previously generated by dart2js) to serve.
  final String jsPath;

  /// HTML file to serve, if any.
  final String htmlPath;

  /// Contents of jsPath, adjusted to use the appropriate server url.
  String jsCode;

  /// Location where we'll dump the coverage data.
  final String outPath;

  /// Uri prefix used on all requests to this server. This will be injected into
  /// the .js file.
  final String prefix;

  // TODO(sigmund): add support to load also simple HTML files to test small
  // simple apps.

  /// Data received so far. The data is just an array of pairs, showing the
  /// hashCode and name of the element used. This can be later cross-checked
  /// against dump-info data.
  Map data = {};

  String get _serializedData => new JsonEncoder.withIndent(' ').convert(data);

  _Server(this.hostname, this.port, String jsPath, this.htmlPath, this.outPath,
      String prefix)
      : jsPath = jsPath,
        jsCode = _adjustRequestUrl(new File(jsPath).readAsStringSync(), prefix),
        prefix = _normalize(prefix);

  run() async {
    await shelf.serve(_handler, hostname, port);
    var urlBase = "http://$hostname:$port${prefix == '' ? '/' : '/$prefix/'}";
    var htmlFilename = htmlPath == null ? '' : path.basename(htmlPath);
    print("Server is listening\n"
        "  - html page: $urlBase$htmlFilename\n"
        "  - js code: $urlBase${path.basename(jsPath)}\n"
        "  - coverage reporting: ${urlBase}coverage\n");
  }

  _expectedPath(String tail) => prefix == '' ? tail : '$prefix/$tail';

  _handler(shelf.Request request) async {
    var urlPath = request.url.path;
    print('received request: $urlPath');
    var baseJsName = path.basename(jsPath);
    var baseHtmlName = htmlPath == null ? '' : path.basename(htmlPath);

    // Serve an HTML file at the default prefix, or a path matching the HTML
    // file name
    if (urlPath == prefix ||
        urlPath == '$prefix/' ||
        urlPath == _expectedPath(baseHtmlName)) {
      var contents = htmlPath == null
          ? '<html><script src="$baseJsName"></script>'
          : await new File(htmlPath).readAsString();
      return new shelf.Response.ok(contents, headers: HTML_HEADERS);
    }

    if (urlPath == _expectedPath(baseJsName)) {
      return new shelf.Response.ok(jsCode, headers: JS_HEADERS);
    }

    // Handle POST requests to record coverage data, and GET requests to display
    // the currently coverage results.
    if (urlPath == _expectedPath('coverage')) {
      if (request.method == 'GET') {
        return new shelf.Response.ok(_serializedData, headers: TEXT_HEADERS);
      }

      if (request.method == 'POST') {
        _record(jsonDecode(await request.readAsString()));
        return new shelf.Response.ok("Thanks!");
      }
    }

    // Any other request is not supported.
    return new shelf.Response.notFound('Not found: "$urlPath"');
  }

  _record(List entries) {
    for (var entry in entries) {
      var id = entry[0];
      data.putIfAbsent('$id', () => {'name': entry[1], 'count': 0});
      data['$id']['count']++;
    }
    _enqueueSave();
  }

  bool _savePending = false;
  int _total = 0;
  _enqueueSave() async {
    if (!_savePending) {
      _savePending = true;
      await new Future.delayed(new Duration(seconds: 3));
      await new File(outPath).writeAsString(_serializedData);
      var diff = data.length - _total;
      print(diff == 0
          ? ' - no new element covered'
          : ' - $diff new elements covered');
      _savePending = false;
      _total = data.length;
    }
  }
}

/// Removes leading and trailing slashes of [uriPath].
_normalize(String uriPath) {
  if (uriPath.startsWith('/')) uriPath = uriPath.substring(1);
  if (uriPath.endsWith('/')) uriPath = uriPath.substring(0, uriPath.length - 1);
  return uriPath;
}

_adjustRequestUrl(String code, String prefix) {
  var newUrl = prefix == '' ? 'coverage' : '$prefix/coverage';
  return code.replaceFirst('"/coverage_uri_to_amend_by_server"',
      '"/$newUrl" /*url-prefix updated!*/');
}

const HTML_HEADERS = const {'content-type': 'text/html'};
const JS_HEADERS = const {'content-type': 'text/javascript'};
const TEXT_HEADERS = const {'content-type': 'text/plain'};
