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

  /// Handle a request to upgrade to a WebSocket.
  void handleWebSocketRequest(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 _maxPrintBufferLength = 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 > _maxPrintBufferLength) {
      _printBuffer.removeRange(0, _printBuffer.length - _maxPrintBufferLength);
    }
  }

  /// 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) {
      if (WebSocketTransformer.isUpgradeRequest(request) &&
          // For WebSockets, verify we're same origin (since the browser would
          // not).
          request.headers.value('origin') == request.requestedUri.origin) {
        _httpHandler.handleWebSocketRequest(request);
      } else if (request.method == 'GET') {
        _httpHandler.handleGetRequest(request);
      } else if (request.method == 'POST') {
        _httpHandler.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;
    response.write('Not found');
    response.close();
  }
}
