// 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;

  /// The number of log entries to show on a result page.
  final int pageLength;

  /// Initialize a newly created server.
  WebServer(this.log, {required this.pageLength});

  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 = pageLength;
    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);
  }
}
