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

import 'dart:async';
import 'dart:convert';

import 'package:logging/logging.dart';
import 'package:observatory/service.dart';

// Export the service library.
export 'package:observatory/service.dart';

/// Description of a VM target.
class WebSocketVMTarget {
  // Last time this VM has been connected to.
  int lastConnectionTime = 0;
  bool get hasEverConnected => lastConnectionTime > 0;

  // Chrome VM or standalone;
  bool chrome = false;
  bool get standalone => !chrome;

  // User defined name.
  String name;
  // Network address of VM.
  String networkAddress;

  WebSocketVMTarget(this.networkAddress) {
    name = networkAddress;
  }

  WebSocketVMTarget.fromMap(Map json) {
    lastConnectionTime = json['lastConnectionTime'];
    chrome = json['chrome'];
    name = json['name'];
    networkAddress = json['networkAddress'];
    if (name == null) {
      name = networkAddress;
    }
  }

  Map toJson() {
    return {
      'lastConnectionTime': lastConnectionTime,
      'chrome': chrome,
      'name': name,
      'networkAddress': networkAddress,
    };
  }
}

class _WebSocketRequest {
  final String id;
  final Completer<String> completer;
  _WebSocketRequest(this.id)
      : completer = new Completer<String>();
}

/// Minimal common interface for 'WebSocket' in [dart:io] and [dart:html].
abstract class CommonWebSocket {
  void connect(String address,
               void onOpen(),
               void onMessage(dynamic data),
               void onError(),
               void onClose());
  bool get isOpen;
  void send(dynamic data);
  void close();
}

/// A [CommonWebSocketVM] communicates with a Dart VM over a CommonWebSocket.
/// The Dart VM can be embedded in Chromium or standalone. In the case of
/// Chromium, we make the service requests via the Chrome Remote Debugging
/// Protocol.
abstract class CommonWebSocketVM extends VM {
  final Completer _connected = new Completer();
  final Completer _disconnected = new Completer();
  final WebSocketVMTarget target;
  final Map<String, _WebSocketRequest> _delayedRequests =
        new Map<String, _WebSocketRequest>();
  final Map<String, _WebSocketRequest> _pendingRequests =
      new Map<String, _WebSocketRequest>();
  int _requestSerial = 0;
  bool _hasInitiatedConnect = false;

  CommonWebSocket _webSocket;

  CommonWebSocketVM(this.target, this._webSocket) {
    assert(target != null);
  }

  void _notifyConnect() {
    if (!_connected.isCompleted) {
      Logger.root.info('WebSocketVM connection opened: ${target.networkAddress}');
      _connected.complete(this);
    }
  }
  Future get onConnect => _connected.future;
  void _notifyDisconnect() {
    if (!_disconnected.isCompleted) {
      Logger.root.info('WebSocketVM connection error: ${target.networkAddress}');
      _disconnected.complete(this);
    }
  }
  Future get onDisconnect => _disconnected.future;

  void disconnect() {
    if (_hasInitiatedConnect) {
      _webSocket.close();
    }
    _cancelAllRequests();
    _notifyDisconnect();
  }

  Future<String> getString(String id) {
    if (!_hasInitiatedConnect) {
      _hasInitiatedConnect = true;
      _webSocket.connect(
          target.networkAddress, _onOpen, _onMessage, _onError, _onClose);
    }
    return _makeRequest(id);
  }

  /// Add a request for [id] to pending requests.
  Future<String> _makeRequest(String id) {
    assert(_hasInitiatedConnect);
    // Create request.
    String serial = (_requestSerial++).toString();
    var request = new _WebSocketRequest(id);
    if (_webSocket.isOpen) {
      // Already connected, send request immediately.
      _sendRequest(serial, request);
    } else {
      // Not connected yet, add to delayed requests.
      _delayedRequests[serial] = request;
    }
    return request.completer.future;
  }

  void _onClose() {
    _cancelAllRequests();
    _notifyDisconnect();
  }

  // WebSocket error event handler.
  void _onError() {
    _cancelAllRequests();
    _notifyDisconnect();
  }

  // WebSocket open event handler.
  void _onOpen() {
    target.lastConnectionTime = new DateTime.now().millisecondsSinceEpoch;
    _sendAllDelayedRequests();
    _notifyConnect();
  }

  // WebSocket message event handler.
  void _onMessage(dynamic data) {
    assert(data is String);  // We don't handle binary data, yet.
    var map = JSON.decode(data);
    if (map == null) {
      Logger.root.severe('WebSocketVM got empty message');
      return;
    }
    // Extract serial and response.
    var serial;
    var response;
    if (target.chrome) {
      if (map['method'] != 'Dart.observatoryData') {
        // ignore devtools protocol spam.
        return;
      }
      serial = map['params']['id'].toString();
      response = map['params']['data'];
    } else {
      serial = map['seq'];
      response = map['response'];
    }
    if (serial == null) {
      // Messages without sequence numbers are asynchronous events
      // from the vm.
      postEventMessage(response);
      return;
    }
    // Complete request.
    var request = _pendingRequests.remove(serial);
    if (request == null) {
      Logger.root.severe('Received unexpected message: ${map}');
      return;
    }
    request.completer.complete(response);
  }

  String _generateNetworkError(String userMessage) {
    return JSON.encode({
      'type': 'ServiceException',
      'id': '',
      'kind': 'NetworkException',
      'message': userMessage
    });
  }

  void _cancelRequests(Map<String, _WebSocketRequest> requests) {
    requests.forEach((String serial, _WebSocketRequest request) {
      request.completer.complete(
          _generateNetworkError('WebSocket disconnected'));
    });
    requests.clear();
  }

  /// Cancel all pending and delayed requests by completing them with an error.
  void _cancelAllRequests() {
    if (_pendingRequests.length > 0) {
      Logger.root.info('Cancelling all pending requests.');
      _cancelRequests(_pendingRequests);
    }
    if (_delayedRequests.length > 0) {
      Logger.root.info('Cancelling all delayed requests.');
      _cancelRequests(_delayedRequests);
    }
  }

  /// Send all delayed requests.
  void _sendAllDelayedRequests() {
    assert(_webSocket.isOpen);
    if (_delayedRequests.length == 0) {
      return;
    }
    Logger.root.info('Sending all delayed requests.');
    // Send all delayed requests.
    _delayedRequests.forEach(_sendRequest);
    // Clear all delayed requests.
    _delayedRequests.clear();
  }

  /// Send the request over WebSocket.
  void _sendRequest(String serial, _WebSocketRequest request) {
    assert (_webSocket.isOpen);
    if (!request.id.endsWith('/profile/tag')) {
      Logger.root.info('GET ${request.id} from ${target.networkAddress}');
    }
    // Mark request as pending.
    assert(_pendingRequests.containsKey(serial) == false);
    _pendingRequests[serial] = request;
    var message;
    // Encode message.
    if (target.chrome) {
      message = JSON.encode({
        'id': int.parse(serial),
        'method': 'Dart.observatoryQuery',
        'params': {
          'id': serial,
          'query': request.id
        }
      });
    } else {
      message = JSON.encode({'seq': serial, 'request': request.id});
    }
    // Send message.
    _webSocket.send(message);
  }
}
