// 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:convert' show jsonDecode, utf8;

import 'dart:isolate' show RawReceivePort;

import 'dart:io';

import 'package:front_end/src/fasta/crash.dart' show defaultServerAddress;

badRequest(HttpRequest request, int status, String message) {
  request.response.statusCode = status;
  request.response.write('''
<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="utf-8">
    <title>$message</title>
  </head>
  <body>
    <h1>$message</h1>
  </body>
</html>
''');
  request.response.close().catchError((e, s) {
    print("Request error: $e.");
  });
  print("${request.uri}: $message");
}

collectLog(DateTime time, HttpRequest request) async {
  String json = await request.transform(utf8.decoder).join();
  var data;
  try {
    data = jsonDecode(json);
  } on FormatException catch (e) {
    print(e);
    return badRequest(
        request, HttpStatus.badRequest, "Malformed JSON data: ${e.message}.");
  }
  if (data is! Map) {
    return badRequest(
        request, HttpStatus.badRequest, "Malformed JSON data: not a map.");
  }
  if (data["type"] != "crash") {
    return badRequest(request, HttpStatus.badRequest,
        "Malformed JSON data: type should be 'crash'.");
  }
  request.response.close();
  String year = "${time.year}".padLeft(4, "0");
  String month = "${time.month}".padLeft(2, "0");
  String day = "${time.day}".padLeft(2, "0");
  String us = "${time.microsecondsSinceEpoch}".padLeft(19, '0');
  Uri uri = Uri.base
      .resolve("crash_logs/${data['client']}/$year-$month-$day/$us.log");
  File file = new File.fromUri(uri);
  await file.parent.create(recursive: true);
  await file.writeAsString(json);
  print("Wrote ${uri.toFilePath()}");

  String type = data["type"];
  String text = data["uri"];
  uri = text == null ? null : Uri.parse(text);
  int charOffset = data["offset"];
  var error = data["error"];
  text = data["trace"];
  StackTrace trace = text == null ? null : new StackTrace.fromString(text);
  String client = data["client"];
  print("""
date: ${time}
type: $type
client: $client
uri: $uri
offset: $charOffset
error:
$error
trace:
$trace
""");
}

main(List<String> arguments) async {
  RawReceivePort keepAlive = new RawReceivePort();
  Uri uri;
  if (arguments.length == 1) {
    uri = Uri.base.resolve(arguments.single);
  } else if (arguments.length == 0) {
    uri = Uri.parse(defaultServerAddress);
  } else {
    throw "Unexpected arguments: ${arguments.join(' ')}.";
  }
  int port = uri.hasPort ? uri.port : 0;
  var host = uri.host.isEmpty ? InternetAddress.loopbackIPv4 : uri.host;
  HttpServer server = await HttpServer.bind(host, port);
  print("Listening on http://${server.address.host}:${server.port}/");
  await for (HttpRequest request in server) {
    if (request.method != "POST") {
      badRequest(request, HttpStatus.methodNotAllowed, "Not allowed.");
      continue;
    }
    if (request.uri.path != "/") {
      badRequest(request, HttpStatus.notFound, "Not found.");
      continue;
    }
    collectLog(new DateTime.now(), request);
  }
  keepAlive.close();
}
