// 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 'dart:collection';
import 'dart:io';

import 'log/log.dart';
import 'page/log_page.dart';
import 'page/stats_page.dart';
import 'page/task_page.dart';

/**
 * An exception that is thrown when a request is received that cannot be
 * handled.
 */
class UnknownRequest implements Exception {}

/**
 * A simple web server.
 */
class WebServer {
  /**
   * The path to the page containing a single page from the instrumentation log.
   */
  static final String logPath = '/log';

  /**
   * The path to the page containing statistics about the instrumentation log.
   */
  static final String statsPath = '/stats';

  /**
   * The path to the page containing statistics about the instrumentation log.
   */
  static final String taskPath = '/task';

  /**
   * The content type for HTML responses.
   */
  static final ContentType _htmlContent =
      new ContentType("text", "html", charset: "utf-8");

  /**
   * The instrumentation log being served up.
   */
  final InstrumentationLog log;

  /**
   * Future that is completed with the HTTP server once it is running.
   */
  Future<HttpServer> _server;

  /**
   * Initialize a newly created server.
   */
  WebServer(this.log);

  Map<String, String> getParameterMap(HttpRequest request) {
    Map<String, String> parameterMap = new HashMap<String, String>();
    String query = request.uri.query;
    if (query != null && query.isNotEmpty) {
      List<String> pairs = query.split('&');
      for (String pair in pairs) {
        List<String> parts = pair.split('=');
        String value = parts[1].trim();
        value = value.replaceAll('+', ' ');
        parameterMap[parts[0].trim()] = value;
      }
    }
    return parameterMap;
  }

  /**
   * Return a table mapping the names of properties to the values of those
   * properties that is extracted from the given HTTP [request].
   */
  Future<Map<String, String>> getValueMap(HttpRequest request) async {
    StringBuffer buffer = new StringBuffer();
    await request.forEach((List<int> element) {
      for (int code in element) {
        buffer.writeCharCode(code);
      }
    });
    Map<String, String> valueMap = new HashMap<String, String>();
    String parameters = buffer.toString();
    if (parameters.isNotEmpty) {
      List<String> pairs = parameters.split('&');
      for (String pair in pairs) {
        List<String> parts = pair.split('=');
        String value = parts[1].trim();
        value = value.replaceAll('+', ' ');
        valueMap[parts[0].trim()] = value;
      }
    }
    return valueMap;
  }

  /**
   * Begin serving HTTP requests over the given [port].
   */
  void serveHttp(int port) {
    _server = HttpServer.bind(InternetAddress.loopbackIPv4, port);
    _server.then(_handleServer).catchError((_) {
      /* Ignore errors. */
    });
  }

  /**
   * Handle a GET [request] received by the HTTP server.
   */
  void _handleGetRequest(HttpRequest request) {
    StringBuffer buffer = new StringBuffer();
    try {
      String path = request.uri.path;
      if (path == logPath) {
        _writeLogPage(request, buffer);
      } else if (path == statsPath) {
        _writeStatsPage(request, buffer);
      } else if (path == taskPath) {
        _writeTaskPage(request, buffer);
      } else {
        _returnUnknownRequest(request);
        return;
      }
    } on UnknownRequest {
      _returnUnknownRequest(request);
      return;
    } catch (exception, stackTrace) {
      HttpResponse response = request.response;
      response.statusCode = HttpStatus.ok;
      response.headers.contentType = _htmlContent;
      StringBuffer buffer = new StringBuffer();
      buffer.write('<p><b>Exception while composing page:</b></p>');
      buffer.write('<p>$exception</p>');
      buffer.write('<p>');
      _writeStackTrace(buffer, stackTrace);
      buffer.write('</p>');
      response.write(buffer.toString());
      response.close();
      return;
    }

    HttpResponse response = request.response;
    response.statusCode = HttpStatus.ok;
    response.headers.contentType = _htmlContent;
    response.write(buffer.toString());
    response.close();
  }

  /**
   * Handle a POST [request] received by the HTTP server.
   */
  Future<void> _handlePostRequest(HttpRequest request) async {
    _returnUnknownRequest(request);
  }

  /**
   * Attach a listener to a newly created HTTP server.
   */
  void _handleServer(HttpServer httpServer) {
    httpServer.listen((HttpRequest request) {
      String method = request.method;
      if (method == 'GET') {
        _handleGetRequest(request);
      } else if (method == 'POST') {
        _handlePostRequest(request);
      } else {
        _returnUnknownRequest(request);
      }
    });
  }

  /**
   * Return an error in response to an unrecognized request received by the HTTP
   * server.
   */
  void _returnUnknownRequest(HttpRequest request) {
    HttpResponse response = request.response;
    response.statusCode = HttpStatus.notFound;
    response.headers.contentType =
        new ContentType("text", "html", charset: "utf-8");
    response.write(
        '<html><head></head><body><h3>Page not found: "${request.uri.path}".</h3></body></html>');
    response.close();
  }

  void _writeLogPage(HttpRequest request, StringBuffer buffer) {
    Map<String, String> parameterMap = getParameterMap(request);
    String groupId = parameterMap['group'];
    String startIndex = parameterMap['start'];
    LogPage page = new LogPage(log);
    page.selectedGroup = EntryGroup.withId(groupId ?? 'nonTask');
    if (startIndex != null) {
      page.pageStart = int.parse(startIndex);
    } else {
      page.pageStart = 0;
    }
    page.pageLength = 25;
    page.writePage(buffer);
  }

  /**
   * Write a representation of the given [stackTrace] to the given [sink].
   */
  void _writeStackTrace(StringSink sink, StackTrace stackTrace) {
    if (stackTrace != null) {
      String trace = stackTrace.toString().replaceAll('#', '<br>#');
      if (trace.startsWith('<br>#')) {
        trace = trace.substring(4);
      }
      sink.write('<p>');
      sink.write(trace);
      sink.write('</p>');
    }
  }

  void _writeStatsPage(HttpRequest request, StringBuffer buffer) {
    new StatsPage(log).writePage(buffer);
  }

  void _writeTaskPage(HttpRequest request, StringBuffer buffer) {
    Map<String, String> parameterMap = getParameterMap(request);
    String analysisStart = parameterMap['analysisStart'];
    String start = parameterMap['start'];
    TaskPage page = new TaskPage(log);
    if (analysisStart == null) {
      throw new UnknownRequest();
    }
    page.analysisStart = int.parse(analysisStart);
    if (start != null) {
      page.pageStart = int.parse(start);
    } else {
      page.pageStart = 0;
    }
    page.pageLength = 25;
    page.writePage(buffer);
  }
}
