// Copyright (c) 2014, 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:io';

import 'package:analysis_server/src/socket_server.dart';
import 'package:analysis_server/src/status/diagnostics.dart';

/**
 * Instances of the class [AbstractGetHandler] handle GET requests.
 */
abstract class AbstractGetHandler {
  /**
   * Handle a GET request received by the HTTP server.
   */
  void handleGetRequest(HttpRequest request);
}

/**
 * An [AbstractGetHandler] that always returns the given error message.
 */
class ErrorGetHandler extends AbstractGetHandler {
  final String message;

  ErrorGetHandler(this.message);

  @override
  void handleGetRequest(HttpRequest request) {
    HttpResponse response = request.response;
    response.statusCode = HttpStatus.notFound;
    response.headers.contentType = ContentType.text;
    response.write(message);
    response.close();
  }
}

/**
 * Instances of the class [HttpServer] implement a simple HTTP server. The
 * server:
 *
 * - listens for an UPGRADE request in order to start an analysis server
 * - serves diagnostic information as html pages
 */
class HttpAnalysisServer {
  /**
   * Number of lines of print output to capture.
   */
  static const int MAX_PRINT_BUFFER_LENGTH = 1000;

  /**
   * An object that can handle either a WebSocket connection or a connection
   * to the client over stdio.
   */
  SocketServer socketServer;

  /**
   * An object that can handle GET requests.
   */
  AbstractGetHandler getHandler;

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

  /**
   * Last PRINT_BUFFER_LENGTH lines printed.
   */
  List<String> _printBuffer = <String>[];

  /**
   * Initialize a newly created HTTP server.
   */
  HttpAnalysisServer(this.socketServer);

  /**
   * Return the port this server is bound to.
   */
  Future<int> get boundPort async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    return (await _serverFuture)?.port;
  }

  void close() {
    _serverFuture?.then((HttpServer server) {
      server.close();
    });
  }

  /**
   * Record that the given line was printed out by the analysis server.
   */
  void recordPrint(String line) {
    _printBuffer.add(line);
    if (_printBuffer.length > MAX_PRINT_BUFFER_LENGTH) {
      _printBuffer.removeRange(
          0, _printBuffer.length - MAX_PRINT_BUFFER_LENGTH);
    }
  }

  /**
   * Begin serving HTTP requests over the given port.
   */
  Future<int> serveHttp([int initialPort]) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    if (_serverFuture != null) {
      return boundPort;
    }

    try {
      _serverFuture =
          HttpServer.bind(InternetAddress.loopbackIPv4, initialPort ?? 0);

      HttpServer server = await _serverFuture;
      _handleServer(server);
      return server.port;
    } catch (ignore) {
      // If we can't bind to the specified port, don't remember the broken
      // server.
      _serverFuture = null;

      return null;
    }
  }

  /**
   * Handle a GET request received by the HTTP server.
   */
  Future<Null> _handleGetRequest(HttpRequest request) async {
    // TODO(brianwilkerson) Determine whether this await is necessary.
    await null;
    if (getHandler == null) {
      getHandler = new DiagnosticsSite(socketServer, _printBuffer);
    }
    await getHandler.handleGetRequest(request);
  }

  /**
   * Attach a listener to a newly created HTTP server.
   */
  void _handleServer(HttpServer httpServer) {
    httpServer.listen((HttpRequest request) async {
      // TODO(brianwilkerson) Determine whether this await is necessary.
      await null;
      List<String> updateValues = request.headers[HttpHeaders.upgradeHeader];
      if (request.method == 'GET') {
        await _handleGetRequest(request);
      } else if (updateValues != null &&
          updateValues.indexOf('websocket') >= 0) {
        // We no longer support serving analysis server communications over
        // WebSocket connections.
        HttpResponse response = request.response;
        response.statusCode = HttpStatus.notFound;
        response.headers.contentType = ContentType.text;
        response.write(
            'WebSocket connections not supported (${request.uri.path}).');
        response.close();
      } 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 = ContentType.text;
    response.write('Not found');
    response.close();
  }
}
