// 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: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);
}

/// 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.
  AbstractSocketServer 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.
  final 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 {
    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 {
    if (_serverFuture != null) {
      return boundPort;
    }

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

      var 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<void> _handleGetRequest(HttpRequest request) async {
    getHandler ??= DiagnosticsSite(socketServer, _printBuffer);
    // TODO(brianwilkerson) Determine if await is necessary, if so, change the
    // return type of [AbstractGetHandler.handleGetRequest] to `Future<void>`.
    await (getHandler.handleGetRequest(request) as dynamic);
  }

  /// Attach a listener to a newly created HTTP server.
  void _handleServer(HttpServer httpServer) {
    httpServer.listen((HttpRequest request) async {
      var updateValues = request.headers[HttpHeaders.upgradeHeader];
      if (request.method == 'GET') {
        await _handleGetRequest(request);
      } else if (updateValues != null && updateValues.contains('websocket')) {
        // We no longer support serving analysis server communications over
        // WebSocket connections.
        var 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) {
    var response = request.response;
    response.statusCode = HttpStatus.notFound;
    response.headers.contentType = ContentType.text;
    response.write('Not found');
    response.close();
  }
}
