// 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.

part of zircon;

// ignore_for_file: public_member_api_docs

class ChannelReaderError {
  final Object error;
  final StackTrace stacktrace;

  ChannelReaderError(this.error, this.stacktrace);

  @override
  String toString() => error.toString();
}

typedef ChannelReaderReadableHandler = void Function();
typedef ChannelReaderErrorHandler = void Function(ChannelReaderError error);

class ChannelReader {
  Channel get channel => _channel;
  Channel _channel;

  bool get isBound => _channel != null;

  HandleWaiter _waiter;

  ChannelReaderReadableHandler onReadable;
  ChannelReaderErrorHandler onError;

  void bind(Channel channel) {
    if (isBound) {
      throw ZirconApiError('ChannelReader is already bound.');
    }
    _channel = channel;
    _asyncWait();
  }

  Channel unbind() {
    if (!isBound) {
      throw ZirconApiError('ChannelReader is not bound');
    }
    _waiter?.cancel();
    final Channel result = _channel;
    _channel = null;
    return result;
  }

  void close() {
    if (!isBound) {
      return;
    }
    _waiter.cancel();
    _channel.close();
    _channel = null;
  }

  void _asyncWait() {
    _waiter = _channel.handle
        .asyncWait(Channel.READABLE | Channel.PEER_CLOSED, _handleWaitComplete);
  }

  void _errorSoon(ChannelReaderError error) {
    if (onError == null) {
      return;
    }
    scheduleMicrotask(() {
      // We need to re-check onError because it might have changed during the
      // asynchronous gap.
      if (onError != null) {
        onError(error);
      }
    });
  }

  @override
  String toString() => 'ChannelReader($_channel)';

  void _handleWaitComplete(int status, int pending) {
    assert(isBound);
    if (status != ZX.OK) {
      close();
      _errorSoon(ChannelReaderError(
          'Wait completed with status ${getStringForStatus(status)} ($status)',
          null));
      return;
    }
    // TODO(abarth): Change this try/catch pattern now that we don't use
    // RawReceivePort any more.
    try {
      if ((pending & Channel.READABLE) != 0) {
        if (onReadable != null) {
          onReadable();
        }
        if (isBound) {
          _asyncWait();
        }
      } else if ((pending & Channel.PEER_CLOSED) != 0) {
        close();
        _errorSoon(ChannelReaderError('Peer unexpectedly closed', null));
      }
      // ignore: avoid_catching_errors
    } on Error catch (_) {
      // An Error exception from the core libraries is probably a programming
      // error that can't be handled. We rethrow the error so that
      // FidlEventHandlers can't swallow it by mistake.
      rethrow;
      // ignore: avoid_catches_without_on_clauses
    } catch (e, s) {
      print(e);
      close();
      _errorSoon(ChannelReaderError(e, s));
    }
  }
}
