// 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.

library http.server;

import 'dart:io';

import 'package:args/args.dart';

import 'src/analysis_server.dart';
import 'src/channel.dart';
import 'src/domain_context.dart';
import 'src/domain_server.dart';
import 'src/get_handler.dart';

/**
 * Instances of the class [HttpServer] implement a simple HTTP server. The
 * primary responsibility of this server is to listen for an UPGRADE request and
 * to start an analysis server
 */
class HttpAnalysisServer {
  /**
   * The name of the application that is used to start a server.
   */
  static const BINARY_NAME = 'server';

  /**
   * The name of the option used to print usage information.
   */
  static const String HELP_OPTION = "help";

  /**
   * The name of the option used to specify the port to which the server will
   * connect.
   */
  static const String PORT_OPTION = "port";

  /**
   * The analysis server that was created when an UPGRADE request was received,
   * or `null` if no such request has yet been received.
   */
  AnalysisServer server;

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

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

  /**
   * Use the given command-line arguments to start this server.
   */
  void start(List<String> args) {
    ArgParser parser = new ArgParser();
    parser.addFlag(
        HELP_OPTION,
        help: "print this help message without starting a server",
        defaultsTo: false,
        negatable: false);
    parser.addOption(
        PORT_OPTION,
        help: "[port] the port on which the server will listen");

    ArgResults results = parser.parse(args);
    if (results[HELP_OPTION]) {
      _printUsage(parser);
      return;
    }
    if (results[PORT_OPTION] == null) {
      print('Missing required port number');
      print('');
      _printUsage(parser);
      return;
    }

    try {
      int port = int.parse(results[PORT_OPTION]);
      HttpServer.bind(InternetAddress.LOOPBACK_IP_V4, port).then(_handleServer);
      print('Listening on port $port');
    } on FormatException {
      print('Invalid port number: ${results[PORT_OPTION]}');
      print('');
      _printUsage(parser);
      return;
    }
  }

  /**
   * Attach a listener to a newly created HTTP server.
   */
  void _handleServer(HttpServer server) {
    server.listen((HttpRequest request) {
      List<String> updateValues = request.headers[HttpHeaders.UPGRADE];
      if (updateValues != null && updateValues.indexOf('websocket') >= 0) {
        if (server != null) {
          _returnServerAlreadyStarted(request);
          return;
        }
        WebSocketTransformer.upgrade(request).then((WebSocket websocket) {
          _handleWebSocket(websocket);
        });
      } else if (request.method == 'GET') {
        _handleGetRequest(request);
      } else {
        _returnUnknownRequest(request);
      }
    });
  }

  /**
   * Handle a GET request received by the HTTP server.
   */
  void _handleGetRequest(HttpRequest request) {
    if (getHandler == null) {
      getHandler = new GetHandler();
      getHandler.server = server;
    }
    getHandler.handleGetRequest(request);
  }

  /**
   * Handle an UPGRADE request received by the HTTP server by creating and
   * running an analysis server on a [WebSocket]-based communication channel.
   */
  void _handleWebSocket(WebSocket socket) {
    server = new AnalysisServer(new WebSocketChannel(socket));
    _initializeHandlers(server);
    if (getHandler != null) {
      getHandler.server = server;
    }
    server.run();
  }

  /**
   * Initialize the handlers to be used by the given [server].
   */
  void _initializeHandlers(AnalysisServer server) {
    server.handlers = [
        new ServerDomainHandler(server),
        new ContextDomainHandler(server),
    ];
  }

  /**
   * Print information about how to use the server.
   */
  void _printUsage(ArgParser parser) {
    print('Usage: $BINARY_NAME [flags]');
    print('');
    print('Supported flags are:');
    print(parser.getUsage());
  }

  /**
   * Return an error in response to an UPGRADE request received after the server
   * has already been started by a previous UPGRADE request.
   */
  void _returnServerAlreadyStarted(HttpRequest request) {
    HttpResponse response = request.response;
    response.statusCode = HttpStatus.SERVICE_UNAVAILABLE;
    response.headers.add(HttpHeaders.CONTENT_TYPE, "text/plain");
    response.write('The server has already been started');
    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();
  }
}
