// Copyright 2018 The Fuchsia Authors. 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:collection';
import 'dart:typed_data';

import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart';

import 'error.dart';
import 'interface.dart';
import 'message.dart';

/// The different states that an [AsyncBinding] or [AsyncProxy] can be in.
enum InterfaceState {
  /// The binding or proxy has not yet been bound.
  unbound,

  /// The binding or proxy has been bound to a channel.
  bound,

  /// The binding or proxy has been closed.
  closed
}

/// An exception that's thrown if an [AsyncBinding] or [AsyncProxy] isn't in the required
/// state for the requested operation.
class FidlStateException extends FidlError {
  /// Create a new [FidlStateException].
  FidlStateException(String message) : super(message);
}

/// A class that holds and mutates the state of an [AsyncBinding] or [AsyncProxy],
/// represented as an [InterfaceState] value.
abstract class _Stateful {
  InterfaceState _currentState = InterfaceState.unbound;

  /// The controller for the stream of state changes.
  final StreamController<InterfaceState> _streamController =
      StreamController.broadcast();

  /// Gets the current state.
  InterfaceState get state => _currentState;

  /// Change the state.
  @protected
  set state(InterfaceState newState) {
    if (_currentState == newState) {
      // No change.
      return;
    }
    if (newState.index < _currentState.index) {
      throw FidlStateException(
          "Can't change InterfaceState from $_currentState to $newState.");
    }
    _currentState = newState;
    _streamController.add(newState);
  }

  /// A stream of state changes.
  Stream<InterfaceState> get stateChanges => _streamController.stream;

  /// Is this interface unbound?
  bool get isUnbound => _currentState == InterfaceState.unbound;

  /// Is this interface bound?
  bool get isBound => _currentState == InterfaceState.bound;

  /// A future that completes when the interface becomes bound.
  Future<void> get whenBound {
    if (_currentState == InterfaceState.unbound) {
      return stateChanges.firstWhere((s) => s == InterfaceState.bound);
    }
    if (_currentState == InterfaceState.bound) {
      return Future.value();
    }
    return Future.error(
        FidlStateException('Interface will never become bound'));
  }

  /// Is this interface closed?
  bool get isClosed => _currentState == InterfaceState.closed;

  /// A future that completes when the interface is closed.
  Future<void> get whenClosed {
    if (_currentState == InterfaceState.closed) {
      return Future.value();
    }
    return stateChanges.firstWhere((s) => s == InterfaceState.closed);
  }
}

/// Listens for messages and dispatches them to an implementation of [T].
abstract class AsyncBinding<T> extends _Stateful {
  /// Creates a binding object in an unbound state.
  ///
  /// Rather than creating a [AsyncBinding<T>] object directly, you typically create
  /// a `TBinding` object, which are subclasses of [AsyncBinding<T>] created by the
  /// FIDL compiler for a specific interface.
  AsyncBinding(this.$interfaceName) {
    _reader
      ..onReadable = _handleReadable
      ..onError = _handleError;
  }

  /// The name of the interface [T] as a string.
  ///
  /// This is used to generate meaningful error messages at runtime.
  final String $interfaceName;

  /// Returns an interface handle whose peer is bound to the given object.
  ///
  /// Creates a channel pair, binds one of the channels to this object, and
  /// returns the other channel. Messages sent over the returned channel will be
  /// decoded and dispatched to `impl`.
  ///
  /// The `impl` parameter must not be null.
  InterfaceHandle<T> wrap(T impl) {
    if (!isUnbound) {
      throw FidlStateException("AsyncBinding<${$interfaceName}> isn't unbound");
    }
    ChannelPair pair = ChannelPair();
    if (pair.status != ZX.OK) {
      throw Exception(
          "AsyncBinding<${$interfaceName}> couldn't create channel: ${getStringForStatus(pair.status)}");
    }
    _impl = impl;
    _reader.bind(pair.first!);

    state = InterfaceState.bound;

    return InterfaceHandle<T>(pair.second);
  }

  /// Binds the given implementation to the given interface request.
  ///
  /// Listens for messages on channel underlying the given interface request,
  /// decodes them, and dispatches the decoded messages to `impl`.
  ///
  /// This object must not already be bound.
  ///
  /// The `impl` and `interfaceRequest` parameters must not be `null`. The
  /// `channel` property of the given `interfaceRequest` must not be `null`.
  ///
  /// Implementation note: in a generic context, the inferred type when creating
  /// the `interfaceRequest` may be a super-class of `T`, possibly `Service`.
  /// Since concrete classes of `AsyncBinding` are code generated, the type
  /// parameter `T` will always be precise, even when used in a generic context.
  /// As a result, we cannot type-bound `interfaceRequest` statically, and
  /// should instead rely on dynamic behavior.
  void bind(T impl, InterfaceRequest<dynamic> interfaceRequest) {
    if (!isUnbound) {
      throw FidlStateException("AsyncBinding<${$interfaceName}> isn't unbound");
    }
    if (impl == null) {
      throw FidlError(
          "AsyncBinding<${$interfaceName}> can't bind to a null impl");
    }

    Channel? channel = interfaceRequest.passChannel();
    if (channel == null) {
      throw FidlError(
          "AsyncBinding<${$interfaceName}> can't bind to a null InterfaceRequest channel");
    }

    _impl = impl;
    _reader.bind(channel);

    state = InterfaceState.bound;
  }

  /// Unbinds [impl] and returns the unbound channel as an interface request.
  ///
  /// Stops listening for messages on the bound channel, wraps the channel in an
  /// interface request of the appropriate type, and returns that interface
  /// request.
  ///
  /// The object must have previously been bound (e.g., using [bind]).
  InterfaceRequest<T> unbind() {
    if (!isBound) {
      throw FidlStateException("AsyncBinding<${$interfaceName}> isn't bound");
    }
    final InterfaceRequest<T> result = InterfaceRequest<T>(_reader.unbind());
    _impl = null;

    state = InterfaceState.closed;

    return result;
  }

  void _writeEpitaph(int statusCode) {
    var bytes = ByteData(24)
      ..setUint32(0, 0) // txid (0 because not tracking this on server side)
      ..setUint8(4, 0) // flags
      ..setUint8(5, 0) // flags
      ..setUint8(6, 0) // flags
      ..setUint8(7, 0) // magic byte
      ..setUint64(8, epitaphOrdinal) // ordinal
      ..setInt32(16, statusCode); // body (epitaph struct)
    _reader.channel?.write(bytes, []);
  }

  /// Close the bound channel.
  ///
  /// This function does nothing if the object is not bound.
  void close([int? statusCode]) {
    if (isBound) {
      if (statusCode != null) {
        _writeEpitaph(statusCode);
      }
      _reader.close();
      _impl = null;

      state = InterfaceState.closed;
    }
  }

  /// The implementation of [T] bound using this object.
  ///
  /// If this object is not bound, this property is null.
  T? get impl => _impl;
  T? _impl;

  /// Decodes the given message and dispatches the decoded message to [impl].
  ///
  /// This function is called by this object whenever a message arrives over a
  /// bound channel.
  @protected
  void handleMessage(IncomingMessage message, OutgoingMessageSink respond);

  void _handleReadable() {
    final ReadEtcResult result = _reader.channel!.queryAndReadEtc();
    if (result.bytes.lengthInBytes == 0) {
      throw FidlError(
          'AsyncBinding<${$interfaceName}> Unexpected empty message or error: $result');
    }

    final IncomingMessage message = IncomingMessage.fromReadEtcResult(result);
    if (!message.isCompatible()) {
      close();
      throw FidlError(
          'Incompatible wire format', FidlErrorCode.fidlUnknownMagic);
    }
    handleMessage(message, sendMessage);
  }

  /// Always called when the channel underneath closes.
  void _handleError(ChannelReaderError error) {
    /// TODO(ianloic): do something with [error].
    close();
  }

  /// Sends the given message over the bound channel.
  ///
  /// If the channel is not bound, the handles inside the message are closed and
  /// the message itself is discarded.
  void sendMessage(OutgoingMessage response) {
    if (!isBound) {
      response.closeHandles();
      return;
    }
    _reader.channel?.writeEtc(response.data, response.handleDispositions);
  }

  final ChannelReader _reader = ChannelReader();
}

/// Representation of a service that all [T] implementations should extend from.
abstract class Service {
  /// Getter for the [ServiceData]
  ServiceData? get $serviceData;
}

/// Exposes the ability to get a hold of the service runtime name and bindings.
abstract class ServiceData<T> {
  /// Returns the generated runtime service name.
  String getName();

  /// Returns the generated runtime service bindings.
  AsyncBinding getBinding();
}

/// Sends messages to a remote implementation of [T]
class AsyncProxy<T> {
  /// Creates a proxy object with the given [ctrl].
  ///
  /// Rather than creating [Proxy<T>] object directly, you typically create
  /// `TProxy` objects, which are subclasses of [Proxy<T>] created by the FIDL
  /// compiler for a specific interface.
  AsyncProxy(this.ctrl);

  /// The control plane for this proxy.
  ///
  /// Methods that manipulate the local proxy (as opposed to sending messages
  /// to the remote implementation of [T]) are exposed on this [ctrl] object to
  /// avoid naming conflicts with the methods of [T].
  final AsyncProxyController<T> ctrl;

  // In general it's probably better to avoid adding fields and methods to this
  // class. Names added to this class have to be mangled by bindings generation
  // to avoid name conflicts.
}

/// A controller for Future based proxies.
class AsyncProxyController<T> extends _Stateful {
  final ChannelReader _reader = ChannelReader();

  final HashMap<int, Completer<dynamic>> _completerMap = HashMap();
  int _nextTxid = 1;

  /// Creates proxy controller.
  ///
  /// Proxy controllers are not typically created directly. Instead, you
  /// typically obtain an [AsyncProxyController<T>] object as the [AsyncProxy<T>.ctrl]
  /// property of a `TProxy` object.
  AsyncProxyController({this.$serviceName, this.$interfaceName}) {
    _reader
      ..onReadable = _handleReadable
      ..onError = _handleError;
    whenClosed.then((_) {
      for (final Completer completer in _completerMap.values) {
        if (!completer.isCompleted) {
          completer.completeError(FidlError(
              'AsyncProxyController<${$interfaceName}> connection closed'));
        }
      }
      _completerMap.clear();
    }, onError: (_) {
      // Ignore errors.
    });
  }

  /// The service name associated with [T], if any.
  ///
  /// Will be set if the `[Discoverable]` attribute is on the FIDL interface
  /// definition. If set it will be the fully-qualified name of the interface.
  ///
  /// This string is typically used with the `ServiceProvider` interface to
  /// request an implementation of [T].
  final String? $serviceName;

  /// The name of the interface of [T].
  ///
  /// Unlike [$serviceName] should always be set and won't be fully qualified.
  /// This should only be used for debugging and logging purposes.
  final String? $interfaceName;

  /// Creates an interface request whose peer is bound to this interface proxy.
  ///
  /// Creates a channel pair, binds one of the channels to this object, and
  /// returns the other channel. Calls to the proxy will be encoded as messages
  /// and sent to the returned channel.
  ///
  /// The proxy must not already have been bound.
  InterfaceRequest<T> request() {
    if (!isUnbound) {
      throw FidlStateException(
          "AsyncProxyController<${$interfaceName}> isn't unbound");
    }

    ChannelPair pair = ChannelPair();
    if (pair.status != ZX.OK) {
      throw FidlError(
          "AsyncProxyController<${$interfaceName}> couldn't create channel: ${getStringForStatus(pair.status)}");
    }
    _reader.bind(pair.first!);
    state = InterfaceState.bound;

    return InterfaceRequest<T>(pair.second);
  }

  /// Binds the proxy to the given interface handle.
  ///
  /// Calls to the proxy will be encoded as messages and sent over the channel
  /// underlying the given interface handle.
  ///
  /// This object must not already be bound.
  ///
  /// The `interfaceHandle` parameter must not be null. The `channel` property
  /// of the given `interfaceHandle` must not be null.
  void bind(InterfaceHandle<T> interfaceHandle) {
    if (!isUnbound) {
      throw FidlStateException(
          "AsyncProxyController<${$interfaceName}> isn't unbound");
    }

    final channel = interfaceHandle.passChannel();
    if (channel == null) {
      throw FidlError(
          "AsyncProxyController<${$interfaceName}> can't bind to null InterfaceHandle channel");
    }

    _reader.bind(channel);
    state = InterfaceState.bound;
  }

  /// Unbinds the proxy and returns the unbound channel as an interface handle.
  ///
  /// Calls on the proxy will no longer be encoded as messages on the bound
  /// channel.
  ///
  /// The proxy must have previously been bound (e.g., using [bind]).
  InterfaceHandle<T> unbind() {
    if (!isBound) {
      throw FidlStateException(
          "AsyncProxyController<${$interfaceName}> isn't bound");
    }
    if (!_reader.isBound) {
      throw FidlError(
          "AsyncProxyController<${$interfaceName}> reader isn't bound");
    }

    state = InterfaceState.closed;

    return InterfaceHandle<T>(_reader.unbind());
  }

  /// Close the channel bound to the proxy.
  ///
  /// The proxy must have previously been bound (e.g., using [bind]).
  void close() {
    _close(null);
  }

  void _close(FidlError? error) {
    if (isBound) {
      _reader.close();
      state = InterfaceState.closed;
      _completerMap.forEach((_, Completer<dynamic> completer) =>
          completer.completeError(FidlStateException(error != null
              ? 'AsyncProxyController<${$interfaceName}> is closed with error: ${error.message}'
              : 'AsyncProxyController<${$interfaceName}> is closed.')));
    }
  }

  ///  close the channel and forwards error to any open completers.
  void proxyError(FidlError error) {
    _close(error);
  }

  /// Called when an epitaph is received (from channel closure).
  EpitaphHandler? onEpitaphReceived;

  /// Called whenever this object receives a response on a bound channel.
  ///
  /// Used by subclasses of [Proxy<T>] to receive responses to messages.
  IncomingMessageSink? onResponse;

  void _handleReadable() {
    final ReadEtcResult result = _reader.channel!.queryAndReadEtc();
    if (result.bytes.lengthInBytes == 0) {
      proxyError(FidlError(
          'AsyncProxyController<${$interfaceName}>: Read from channel failed'));
      return;
    }
    try {
      IncomingMessage message = IncomingMessage.fromReadEtcResult(result);
      final epitaphCallback = onEpitaphReceived;
      final responseCallback = onResponse;
      if (message.ordinal == epitaphOrdinal) {
        int statusCode = message.data.getInt32(16);
        if (epitaphCallback != null) {
          epitaphCallback(statusCode);
        }
      } else if (responseCallback != null) {
        responseCallback(message);
      }
    } on FidlError catch (e) {
      for (HandleInfo handleInfo in result.handleInfos) {
        handleInfo.handle.close();
      }
      proxyError(e);
    }
  }

  /// Always called when the channel underneath closes.
  void _handleError(ChannelReaderError error) {
    proxyError(FidlError(error.toString()));
  }

  /// Sends the given messages over the bound channel.
  ///
  /// Used by subclasses of [Proxy<T>] to send encoded messages.
  void sendMessage(OutgoingMessage message) {
    if (!_reader.isBound) {
      proxyError(FidlStateException(
          'AsyncProxyController<${$interfaceName}> is closed.'));
      return;
    }
    final int status =
        _reader.channel!.writeEtc(message.data, message.handleDispositions);
    if (status != ZX.OK) {
      proxyError(FidlError(
          'AsyncProxyController<${$interfaceName}> failed to write to channel: ${_reader.channel} (status: $status)'));
    }
  }

  /// Sends the given messages over the bound channel and registers a Completer
  /// to handle the response.
  ///
  /// Used by subclasses of [AsyncProxy<T>] to send encoded messages.
  void sendMessageWithResponse(
      OutgoingMessage message, Completer<dynamic> completer) {
    if (!_reader.isBound) {
      proxyError(FidlStateException(
          'AsyncProxyController<${$interfaceName}> is closed.'));
      return;
    }

    const int _userspaceTxidMask = 0x7FFFFFFF;

    int txid = _nextTxid++ & _userspaceTxidMask;
    while (txid == 0 || _completerMap.containsKey(txid))
      txid = _nextTxid++ & _userspaceTxidMask;
    message.txid = txid;
    _completerMap[message.txid] = completer;
    final int status =
        _reader.channel!.writeEtc(message.data, message.handleDispositions);

    if (status != ZX.OK) {
      proxyError(FidlError(
          'AsyncProxyController<${$interfaceName}> failed to write to channel: ${_reader.channel} (status: $status)'));
      return;
    }
  }

  /// Returns the completer associated with the given response message.
  ///
  /// Used by subclasses of [AsyncProxy<T>] to retrieve registered completers when
  /// handling response messages.
  Completer? getCompleter(int txid) {
    final Completer? result = _completerMap.remove(txid);
    if (result == null) {
      proxyError(FidlError('Message had unknown request id: $txid'));
    }
    return result;
  }
}
