// Copyright (c) 2015, 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.

// @dart = 2.5

part of dart.io;

abstract class _IOResourceInfo {
  final String type;
  final int id;
  String get name;
  static int _count = 0;

  static final Stopwatch _sw = new Stopwatch()..start();
  static final _startTime = new DateTime.now().millisecondsSinceEpoch;

  static double get timestamp => _startTime + _sw.elapsedMicroseconds / 1000;

  _IOResourceInfo(this.type) : id = _IOResourceInfo.getNextID();

  /// Get the full set of values for a specific implementation. This is normally
  /// looked up based on an id from a referenceValueMap.
  Map<String, dynamic> get fullValueMap;

  /// The reference map, used to return a list of values, e.g., getting
  /// all open sockets. The structure of this is shared among all subclasses.
  Map<String, dynamic> get referenceValueMap => {
        // The type for a reference object is prefixed with @ in observatory.
        'type': '@$type',
        'id': id,
        'name': name,
      };

  static int getNextID() => _count++;
}

abstract class _ReadWriteResourceInfo extends _IOResourceInfo {
  int totalRead;
  int totalWritten;
  int readCount;
  int writeCount;
  double lastRead;
  double lastWrite;

  // Not all call sites use this. In some cases, e.g., a socket, a read does
  // not always mean that we actually read some bytes (we may do a read to see
  // if there are some bytes available).
  void addRead(int bytes) {
    totalRead += bytes;
    readCount++;
    lastRead = _IOResourceInfo.timestamp;
  }

  // In cases where we read but did not necessarily get any bytes, use this to
  // update the readCount and timestamp. Manually update totalRead if any bytes
  // where actually read.
  void didRead() {
    addRead(0);
  }

  void addWrite(int bytes) {
    totalWritten += bytes;
    writeCount++;
    lastWrite = _IOResourceInfo.timestamp;
  }

  _ReadWriteResourceInfo(String type)
      : totalRead = 0,
        totalWritten = 0,
        readCount = 0,
        writeCount = 0,
        lastRead = 0.0,
        lastWrite = 0.0,
        super(type);

  Map<String, dynamic> get fullValueMap => {
        'type': type,
        'id': id,
        'name': name,
        'totalRead': totalRead,
        'totalWritten': totalWritten,
        'readCount': readCount,
        'writeCount': writeCount,
        'lastRead': lastRead,
        'lastWrite': lastWrite
      };
}

class _FileResourceInfo extends _ReadWriteResourceInfo {
  static const String _type = '_file';

  final file;

  static Map<int, _FileResourceInfo> openFiles =
      new Map<int, _FileResourceInfo>();

  _FileResourceInfo(this.file) : super(_type) {
    FileOpened(this);
  }

  static FileOpened(_FileResourceInfo info) {
    assert(!openFiles.containsKey(info.id));
    openFiles[info.id] = info;
  }

  static FileClosed(_FileResourceInfo info) {
    assert(openFiles.containsKey(info.id));
    openFiles.remove(info.id);
  }

  static Iterable<Map<String, dynamic>> getOpenFilesList() {
    return new List.from(openFiles.values.map((e) => e.referenceValueMap));
  }

  static Future<ServiceExtensionResponse> getOpenFiles(function, params) {
    assert(function == 'ext.dart.io.getOpenFiles');
    var data = {'type': '_openfiles', 'data': getOpenFilesList()};
    var jsonValue = json.encode(data);
    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
  }

  Map<String, dynamic> getFileInfoMap() {
    return fullValueMap;
  }

  static Future<ServiceExtensionResponse> getFileInfoMapByID(function, params) {
    assert(params.containsKey('id'));
    var id = int.parse(params['id']);
    var result =
        openFiles.containsKey(id) ? openFiles[id].getFileInfoMap() : {};
    var jsonValue = json.encode(result);
    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
  }

  String get name {
    return '${file.path}';
  }
}

class _ProcessResourceInfo extends _IOResourceInfo {
  static const String _type = '_process';
  final process;
  final double startedAt;

  static Map<int, _ProcessResourceInfo> startedProcesses =
      new Map<int, _ProcessResourceInfo>();

  _ProcessResourceInfo(this.process)
      : startedAt = _IOResourceInfo.timestamp,
        super(_type) {
    ProcessStarted(this);
  }

  String get name => process._path;

  void stopped() {
    ProcessStopped(this);
  }

  Map<String, dynamic> get fullValueMap => {
        'type': type,
        'id': id,
        'name': name,
        'pid': process.pid,
        'startedAt': startedAt,
        'arguments': process._arguments,
        'workingDirectory':
            process._workingDirectory == null ? '.' : process._workingDirectory,
      };

  static ProcessStarted(_ProcessResourceInfo info) {
    assert(!startedProcesses.containsKey(info.id));
    startedProcesses[info.id] = info;
  }

  static ProcessStopped(_ProcessResourceInfo info) {
    assert(startedProcesses.containsKey(info.id));
    startedProcesses.remove(info.id);
  }

  static Iterable<Map<String, dynamic>> getStartedProcessesList() =>
      new List.from(startedProcesses.values.map((e) => e.referenceValueMap));

  static Future<ServiceExtensionResponse> getStartedProcesses(
      String function, Map<String, String> params) {
    assert(function == 'ext.dart.io.getProcesses');
    var data = {'type': '_startedprocesses', 'data': getStartedProcessesList()};
    var jsonValue = json.encode(data);
    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
  }

  static Future<ServiceExtensionResponse> getProcessInfoMapById(
      String function, Map<String, String> params) {
    var id = int.parse(params['id']);
    var result = startedProcesses.containsKey(id)
        ? startedProcesses[id].fullValueMap
        : {};
    var jsonValue = json.encode(result);
    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
  }
}

class _SocketResourceInfo extends _ReadWriteResourceInfo {
  static const String _tcpString = 'TCP';
  static const String _udpString = 'UDP';
  static const String _type = '_socket';

  final /*_NativeSocket|*/ socket;

  static Map<int, _SocketResourceInfo> openSockets =
      new Map<int, _SocketResourceInfo>();

  _SocketResourceInfo(this.socket) : super(_type) {
    SocketOpened(this);
  }

  String get name {
    if (socket.isListening) {
      return 'listening:${socket.address.host}:${socket.port}';
    }
    var remote = '';
    try {
      var remoteHost = socket.remoteAddress.host;
      var remotePort = socket.remotePort;
      remote = ' -> $remoteHost:$remotePort';
    } catch (e) {} // ignored if we can't get the information
    return '${socket.address.host}:${socket.port}$remote';
  }

  static Iterable<Map<String, dynamic>> getOpenSocketsList() {
    return new List.from(openSockets.values.map((e) => e.referenceValueMap));
  }

  Map<String, dynamic> getSocketInfoMap() {
    var result = fullValueMap;
    result['socketType'] = socket.isTcp ? _tcpString : _udpString;
    result['listening'] = socket.isListening;
    result['host'] = socket.address.host;
    result['port'] = socket.port;
    if (!socket.isListening) {
      try {
        result['remoteHost'] = socket.remoteAddress.host;
        result['remotePort'] = socket.remotePort;
      } catch (e) {
        // UDP.
        result['remotePort'] = 'NA';
        result['remoteHost'] = 'NA';
      }
    } else {
      result['remotePort'] = 'NA';
      result['remoteHost'] = 'NA';
    }
    result['addressType'] = socket.address.type.name;
    return result;
  }

  static Future<ServiceExtensionResponse> getSocketInfoMapByID(
      String function, Map<String, String> params) {
    assert(params.containsKey('id'));
    var id = int.parse(params['id']);
    var result =
        openSockets.containsKey(id) ? openSockets[id].getSocketInfoMap() : {};
    var jsonValue = json.encode(result);
    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
  }

  static Future<ServiceExtensionResponse> getOpenSockets(function, params) {
    assert(function == 'ext.dart.io.getOpenSockets');
    var data = {'type': '_opensockets', 'data': getOpenSocketsList()};
    var jsonValue = json.encode(data);
    return new Future.value(new ServiceExtensionResponse.result(jsonValue));
  }

  static SocketOpened(_SocketResourceInfo info) {
    assert(!openSockets.containsKey(info.id));
    openSockets[info.id] = info;
  }

  static SocketClosed(_SocketResourceInfo info) {
    assert(openSockets.containsKey(info.id));
    openSockets.remove(info.id);
  }
}
