// 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:convert';
import 'dart:io';

import 'package:analysis_server/plugin/protocol/protocol.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/channel/web_socket_channel.dart';

/**
 * [AnalysisManager] is used to launch and manage an analysis server
 * running in a separate process using either the [start] or [connect] methods.
 */
class AnalysisManager {
  // TODO dynamically allocate port and/or allow client to specify port
  static const int PORT = 3333;

  /**
   * The analysis server process being managed
   * or `null` if managing an analysis server that was already running.
   */
  Process process;

  /**
   * The channel used to communicate with the analysis server.
   */
  ClientCommunicationChannel channel;

  /**
   * Stop the analysis server.
   *
   * Returns `true` if the signal is successfully sent and process terminates.
   * Otherwise there was no attached process or the signal could not be sent,
   * usually meaning that the process is already dead.
   */
  Future<bool> stop() {
    if (process == null) {
      return channel.close().then((_) => false);
    }
    return channel
        .sendRequest(new ServerShutdownParams().toRequest('0'))
        .timeout(new Duration(seconds: 2), onTimeout: () {
      print('Expected shutdown response');
    }).then((Response response) {
      return channel.close().then((_) => process.exitCode);
    }).timeout(new Duration(seconds: 2), onTimeout: () {
      print('Expected server to shutdown');
      process.kill();
    }).then((int result) {
      if (result != null && result != 0) {
        exitCode = result;
      }
      return true;
    });
  }

  /**
   * Launch an analysis server and open a connection to that server.
   */
  Future<AnalysisManager> _launchServer(String pathToServer) {
    // TODO dynamically allocate port and/or allow client to specify port
    List<String> serverArgs = [pathToServer, '--port', PORT.toString()];
    return Process.start(Platform.executable, serverArgs).catchError((error) {
      exitCode = 1;
      throw 'Failed to launch analysis server: $error';
    }).then(_listenForPort);
  }

  /**
   * Listen for a port from the given analysis server process.
   */
  Future<AnalysisManager> _listenForPort(Process process) {
    this.process = process;

    // Echo stdout and stderr
    Stream out = process.stdout.transform(UTF8.decoder).asBroadcastStream();
    out.listen((line) => print(line));
    process.stderr.pipe(stderr);

    // Listen for port from server
    const String pattern = 'Listening on port ';
    return out
        .firstWhere((String line) => line.startsWith(pattern))
        .timeout(new Duration(seconds: 10))
        .catchError((error) {
      exitCode = 1;
      process.kill();
      throw 'Expected port from analysis server';
    }).then((String line) {
      String port = line.substring(pattern.length).trim();
      String url = 'ws://${InternetAddress.LOOPBACK_IP_V4.address}:$port/';
      return _openConnection(url);
    });
  }

  /**
   * Open a connection to the analysis server using the given URL.
   */
  Future<AnalysisManager> _openConnection(String serverUrl) {
    Function onError = (error) {
      exitCode = 1;
      if (process != null) {
        process.kill();
      }
      throw 'Failed to connect to analysis server at $serverUrl\n  $error';
    };
    try {
      return WebSocket
          .connect(serverUrl)
          .catchError(onError)
          .then((WebSocket socket) {
        this.channel = new WebSocketClientChannel(socket);
        return this;
      });
    } catch (error) {
      onError(error);
    }
  }

  /**
   * Open a connection to a running analysis server
   * and return a future with a manager for that analysis server.
   */
  static Future<AnalysisManager> connect(String serverUrl) {
    return new AnalysisManager()._openConnection(serverUrl);
  }

  /**
   * Launch analysis server in a separate process
   * and return a future with a manager for that analysis server.
   */
  static Future<AnalysisManager> start(String serverPath) {
    return new AnalysisManager()._launchServer(serverPath);
  }
}
