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

import 'log/log.dart';
import 'page/log_page.dart';
import 'page/stats_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 content type for HTML responses.
  static final ContentType _htmlContent =
      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.
  late Future<HttpServer> _server;

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

  Map<String, String> getParameterMap(HttpRequest request) {
    Map<String, String> parameterMap = HashMap<String, String>();
    var query = request.uri.query;
    if (query.isNotEmpty) {
      var pairs = query.split('&');
      for (var pair in pairs) {
        var parts = pair.split('=');
        var 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 {
    var buffer = StringBuffer();
    await request.forEach((List<int> element) {
      for (var code in element) {
        buffer.writeCharCode(code);
      }
    });
    Map<String, String> valueMap = HashMap<String, String>();
    var parameters = buffer.toString();
    if (parameters.isNotEmpty) {
      var pairs = parameters.split('&');
      for (var pair in pairs) {
        var parts = pair.split('=');
        var 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) {
    var buffer = StringBuffer();
    try {
      var path = request.uri.path;
      if (path == logPath) {
        _writeLogPage(request, buffer);
      } else if (path == statsPath) {
        _writeStatsPage(request, buffer);
      } else {
        _returnUnknownRequest(request);
        return;
      }
    } on UnknownRequest {
      _returnUnknownRequest(request);
      return;
    } catch (exception, stackTrace) {
      var response = request.response;
      response.statusCode = HttpStatus.ok;
      response.headers.contentType = _htmlContent;
      var buffer = 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;
    }

    var 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) {
      var 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) {
    var response = request.response;
    response.statusCode = HttpStatus.notFound;
    response.headers.contentType =
        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) {
    var parameterMap = getParameterMap(request);
    var groupId = parameterMap['group'];
    var startIndex = parameterMap['start'];
    var page = 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) {
    var 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) {
    StatsPage(log).writePage(buffer);
  }
}
