library get.handler;

import 'dart:io';

import 'package:analyzer/src/generated/engine.dart';

import 'package:analysis_server/src/analysis_server.dart';

/**
 * Instances of the class [GetHandler] handle GET requests
 */
class GetHandler {
  /**
   * The path used to request the status of the analysis server as a whole.
   */
  static const String STATUS_PATH = '/status';

  /**
   * The analysis server whose status is to be reported on, or `null` if the
   * server has not yet been created.
   */
  AnalysisServer server;

  /**
   * Initialize a newly created handler for GET requests.
   */
  GetHandler();

  /**
   * Handle a GET request received by the HTTP server.
   */
  void handleGetRequest(HttpRequest request) {
    String path = request.uri.path;
    if (path == STATUS_PATH) {
      _returnServerStatus(request);
    } else {
      _returnUnknownRequest(request);
    }
  }

  /**
   * Return a response indicating the status of the analysis server.
   */
  void _returnServerStatus(HttpRequest request) {
    HttpResponse response = request.response;
    response.statusCode = HttpStatus.OK;
    response.headers.add(HttpHeaders.CONTENT_TYPE, "text/html");
    response.write('<html>');
    response.write('<head>');
    response.write('<title>Dart Analysis Server - Status</title>');
    response.write('</head>');
    response.write('<body>');
    response.write('<h1>Analysis Server</h1>');
    if (server == null) {
      response.write('<p>Not running</p>');
    } else {
      response.write('<p>Running</p>');
      response.write('<h1>Analysis Contexts</h1>');
      response.write('<h2>Summary</h2>');
      response.write('<table>');
      _writeRow(
          response,
          ['Context', 'ERROR', 'FLUSHED', 'IN_PROCESS', 'INVALID', 'VALID'],
          true);
      server.contextMap.forEach((String key, AnalysisContext context) {
        AnalysisContentStatistics statistics =
            (context as AnalysisContextImpl).statistics;
        int errorCount = 0;
        int flushedCount = 0;
        int inProcessCount = 0;
        int invalidCount = 0;
        int validCount = 0;
        statistics.cacheRows.forEach((AnalysisContentStatistics_CacheRow row) {
          errorCount += row.errorCount;
          flushedCount += row.flushedCount;
          inProcessCount += row.inProcessCount;
          invalidCount += row.invalidCount;
          validCount += row.validCount;
        });
        _writeRow(response, [
            '<a href="#context_$key">$key</a>',
            errorCount,
            flushedCount,
            inProcessCount,
            invalidCount,
            validCount]);
      });
      response.write('</table>');
      server.contextMap.forEach((String key, AnalysisContext context) {
        response.write('<h2><a name="context_$key">Analysis Context: $key}</a></h2>');
        AnalysisContentStatistics statistics = (context as AnalysisContextImpl).statistics;
        response.write('<table>');
        _writeRow(
            response,
            ['Item', 'ERROR', 'FLUSHED', 'IN_PROCESS', 'INVALID', 'VALID'],
            true);
        statistics.cacheRows.forEach((AnalysisContentStatistics_CacheRow row) {
          _writeRow(
              response,
              [row.name,
               row.errorCount,
               row.flushedCount,
               row.inProcessCount,
               row.invalidCount,
               row.validCount]);
        });
        response.write('</table>');
        List<AnalysisException> exceptions = statistics.exceptions;
        if (!exceptions.isEmpty) {
          response.write('<h2>Exceptions</h2>');
          exceptions.forEach((AnalysisException exception) {
            response.write('<p>${exception.message}</p>');
          });
        }
      });
    }
    response.write('</body>');
    response.write('</html>');
    response.close();
  }

  /**
   * 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.NOT_FOUND;
    response.headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
    response.write('Not found');
    response.close();
  }

  /**
   * Write a single row within a table to the given [response] object. The row
   * will have one cell for each of the [columns], and will be a header row if
   * [header] is `true`.
   */
  void _writeRow(HttpResponse response, List<Object> columns, [bool header = false]) {
    if (header) {
      response.write('<th>');
    } else {
      response.write('<tr>');
    }
    columns.forEach((Object value) {
      response.write('<td>');
      response.write(value);
      response.write('</td>');
    });
    if (header) {
      response.write('</th>');
    } else {
      response.write('</tr>');
    }
  }
}