// Copyright (c) 2013, 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 vmservice_io;

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:isolate';
import 'dart:typed_data';
import 'dart:_vmservice';

part 'loader.dart';
part 'server.dart';

// The TCP ip/port that the HTTP server listens on.
int _port;
String _ip;
// Should the HTTP server auto start?
bool _autoStart;
// Should the HTTP server run in devmode?
bool _originCheckDisabled;
bool _isWindows = false;
bool _isFuchsia = false;
var _signalWatch;
var _signalSubscription;

// HTTP server.
Server server;
Future<Server> serverFuture;

_lazyServerBoot() {
  if (server != null) {
    return;
  }
  // Lazily create service.
  var service = new VMService();
  // Lazily create server.
  server = new Server(service, _ip, _port, _originCheckDisabled);
}

Future cleanupCallback() async {
  shutdownLoaders();
  // Cancel the sigquit subscription.
  if (_signalSubscription != null) {
    await _signalSubscription.cancel();
    _signalSubscription = null;
  }
  if (server != null) {
    try {
      await server.cleanup(true);
    } catch (e, st) {
      print("Error in vm-service shutdown: $e\n$st\n");
    }
  }
  if (_registerSignalHandlerTimer != null) {
    _registerSignalHandlerTimer.cancel();
    _registerSignalHandlerTimer = null;
  }
  // Call out to embedder's shutdown callback.
  _shutdown();
}

Future<Uri> createTempDirCallback(String base) async {
  Directory temp = await Directory.systemTemp.createTemp(base);
  // Underneath the temporary directory, create a directory with the
  // same name as the DevFS name [base].
  var fsUri = temp.uri.resolveUri(new Uri.directory(base));
  await new Directory.fromUri(fsUri).create();
  return fsUri;
}

Future deleteDirCallback(Uri path) async {
  Directory dir = new Directory.fromUri(path);
  await dir.delete(recursive: true);
}

class PendingWrite {
  PendingWrite(this.uri, this.bytes);
  final Completer completer = new Completer();
  final Uri uri;
  final List<int> bytes;

  Future write() async {
    var file = new File.fromUri(uri);
    var parent_directory = file.parent;
    await parent_directory.create(recursive: true);
    var result = await file.writeAsBytes(bytes);
    completer.complete(null);
    WriteLimiter._writeCompleted();
  }
}

class WriteLimiter {
  static final List<PendingWrite> pendingWrites = new List<PendingWrite>();

  // non-rooted Android devices have a very low limit for the number of
  // open files. Artificially cap ourselves to 16.
  static const kMaxOpenWrites = 16;
  static int openWrites = 0;

  static Future scheduleWrite(Uri path, List<int> bytes) async {
    // Create a new pending write.
    PendingWrite pw = new PendingWrite(path, bytes);
    pendingWrites.add(pw);
    _maybeWriteFiles();
    return pw.completer.future;
  }

  static _maybeWriteFiles() {
    while (openWrites < kMaxOpenWrites) {
      if (pendingWrites.length > 0) {
        PendingWrite pw = pendingWrites.removeLast();
        pw.write();
        openWrites++;
      } else {
        break;
      }
    }
  }

  static _writeCompleted() {
    openWrites--;
    assert(openWrites >= 0);
    _maybeWriteFiles();
  }
}

Future writeFileCallback(Uri path, List<int> bytes) async {
  return WriteLimiter.scheduleWrite(path, bytes);
}

Future writeStreamFileCallback(Uri path, Stream<List<int>> bytes) async {
  var file = new File.fromUri(path);
  var parent_directory = file.parent;
  await parent_directory.create(recursive: true);
  IOSink sink = await file.openWrite();
  await sink.addStream(bytes);
  await sink.close();
}

Future<List<int>> readFileCallback(Uri path) async {
  var file = new File.fromUri(path);
  return await file.readAsBytes();
}

Future<List<Map<String, dynamic>>> listFilesCallback(Uri dirPath) async {
  var dir = new Directory.fromUri(dirPath);
  var dirPathStr = dirPath.path;
  var stream = dir.list(recursive: true);
  var result = <Map<String, dynamic>>[];
  await for (var fileEntity in stream) {
    var filePath = new Uri.file(fileEntity.path).path;
    var stat = await fileEntity.stat();
    if (stat.type == FileSystemEntityType.FILE &&
        filePath.startsWith(dirPathStr)) {
      var map = <String, dynamic>{};
      map['name'] = '/' + filePath.substring(dirPathStr.length);
      map['size'] = stat.size;
      map['modified'] = stat.modified.millisecondsSinceEpoch;
      result.add(map);
    }
  }
  return result;
}

Future<Uri> serverInformationCallback() async {
  _lazyServerBoot();
  return server.serverAddress;
}

Future<Uri> webServerControlCallback(bool enable) async {
  _lazyServerBoot();
  if (server.running == enable) {
    // No change.
    return server.serverAddress;
  }

  if (enable) {
    await server.startup();
    return server.serverAddress;
  } else {
    await server.shutdown(true);
    return server.serverAddress;
  }
}

Null _clearFuture(_) {
  serverFuture = null;
}

_onSignal(ProcessSignal signal) {
  if (serverFuture != null) {
    // Still waiting.
    return;
  }
  _lazyServerBoot();
  // Toggle HTTP server.
  if (server.running) {
    serverFuture = server.shutdown(true).then(_clearFuture);
  } else {
    serverFuture = server.startup().then(_clearFuture);
  }
}

Timer _registerSignalHandlerTimer;

_registerSignalHandler() {
  _registerSignalHandlerTimer = null;
  if (_signalWatch == null) {
    // Cannot register for signals.
    return;
  }
  if (_isWindows || _isFuchsia) {
    // Cannot register for signals on Windows or Fuchsia.
    return;
  }
  _signalSubscription = _signalWatch(ProcessSignal.SIGQUIT).listen(_onSignal);
}

@pragma("vm.entry-point", !const bool.fromEnvironment("dart.vm.product"))
main() {
  // Set embedder hooks.
  VMServiceEmbedderHooks.cleanup = cleanupCallback;
  VMServiceEmbedderHooks.createTempDir = createTempDirCallback;
  VMServiceEmbedderHooks.deleteDir = deleteDirCallback;
  VMServiceEmbedderHooks.writeFile = writeFileCallback;
  VMServiceEmbedderHooks.writeStreamFile = writeStreamFileCallback;
  VMServiceEmbedderHooks.readFile = readFileCallback;
  VMServiceEmbedderHooks.listFiles = listFilesCallback;
  VMServiceEmbedderHooks.serverInformation = serverInformationCallback;
  VMServiceEmbedderHooks.webServerControl = webServerControlCallback;
  // Always instantiate the vmservice object so that the exit message
  // can be delivered and waiting loaders can be cancelled.
  new VMService();
  if (_autoStart) {
    _lazyServerBoot();
    server.startup();
    // It's just here to push an event on the event loop so that we invoke the
    // scheduled microtasks.
    Timer.run(() {});
  }
  scriptLoadPort.handler = _processLoadRequest;
  // Register signal handler after a small delay to avoid stalling main
  // isolate startup.
  _registerSignalHandlerTimer = new Timer(shortDelay, _registerSignalHandler);
  return scriptLoadPort;
}

_shutdown() native "VMServiceIO_Shutdown";
