// 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 [AbstractHttpHandler] handle HTTP requests.
abstract class AbstractHttpHandler {
  /// Handle a GET request received by the HTTP server.
  void handleGetRequest(HttpRequest request);

  /// Handle a POST request received by the HTTP server.
  void handlePostRequest(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.
  final AbstractSocketServer _socketServer;

  /// An object that can handle HTTP requests.
  late final AbstractHttpHandler _httpHandler = DiagnosticsSite(
    _socketServer,
    _printBuffer,
  );

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

  /// 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') {
        _httpHandler.handleGetRequest(request);
      } else if (request.method == 'POST') {
        _httpHandler.handlePostRequest(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}).',
        );
        unawaited(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();
  }
}
