// Copyright 2017 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:convert';
import 'dart:typed_data';

import 'package:fidl_fuchsia_ledger/fidl_async.dart';
import 'package:fidl_fuchsia_io/fidl_async.dart' as io;
import 'package:fidl_fuchsia_sys/fidl_async.dart';
import 'package:fidl/fidl.dart';
import 'package:fidl_fuchsia_xi/fidl_async.dart' as service;
import 'package:fuchsia_services/services.dart';
import 'package:xi_client/client.dart';
import 'package:zircon/zircon.dart';

/// A partial implementation of XiClient to handle socket reading and writing.
/// This should not be used on its own, but subclassed by some another type
/// that will handle setting up the socket.
class FuchsiaSocketClient extends XiClient {
  final SocketReader _reader = SocketReader();

  @override
  Future<Null> init() async {}

  @override
  void send(String data) {
    final List<int> ints = utf8.encode('$data\n');
    final Uint8List bytes = Uint8List.fromList(ints);
    final ByteData buffer = bytes.buffer.asByteData();

    final WriteResult result = _reader.socket.write(buffer);

    if (result.status != ZX.OK) {
      StateError error = StateError('ERROR WRITING: $result');
      streamController
        ..addError(error)
        ..close();
    }
  }

  /// Callback used to handle `SocketReader`'s onReadable event. This event
  /// listener will read data from the socket and pump it through the
  /// [XiClient] transformation pipeline.
  void handleRead() {
    // TODO(pylaligand): the number of bytes below is bogus.
    final ReadResult result = _reader.socket.read(1000);

    if (result.status != ZX.OK) {
      StateError error = StateError('Socket read error: ${result.status}');
      streamController
        ..addError(error)
        ..close();
      return;
    }

    String resultAsString = result.bytesAsUTF8String();
    // TODO: use string directly, avoid re-roundtrip
    List<int> fragment = utf8.encode(resultAsString);
    streamController.add(fragment);
  }
}

/// Fuchsia specific [XiClient].
class XiFuchsiaClient extends FuchsiaSocketClient {
  /// Constructor.
  /// ignore: avoid_unused_constructor_parameters
  XiFuchsiaClient(InterfaceHandle<Ledger> _ledgerHandle) {
    // Note: _ledgerHandle is currently unused, but we're hoping to bring it back.
  }
  final _dirProxy = io.DirectoryProxy();
  final service.JsonProxy _jsonProxy = service.JsonProxy();

  @override
  Future<Null> init() async {
    if (initialized) {
      return;
    }

    // Creates a new instance of the component described by launchInfo.
    final componentController = ComponentControllerProxy();

    // Create and connect to a Launcher service
    final launcherProxy = LauncherProxy();
    StartupContext.fromStartupInfo().incoming.connectToService(launcherProxy);

    // Use the launcher services launch echo server via launchInfo
    final LaunchInfo launchInfo = LaunchInfo(
        url: 'fuchsia-pkg://fuchsia.com/xi_core#meta/xi_core.cmx',
        directoryRequest: _dirProxy.ctrl.request().passChannel());
    await launcherProxy.createComponent(
        launchInfo, componentController.ctrl.request());

    // Close launcher connection since we no longer need the launcher service.
    launcherProxy.ctrl.close();

    Incoming(_dirProxy).connectToService(_jsonProxy);

    final SocketPair pair = SocketPair();
    await _jsonProxy.connectSocket(pair.first);
    _reader
      ..bind(pair.second)
      ..onReadable = handleRead;

    initialized = true;
  }

  @override
  void send(String data) {
    if (initialized == false) {
      throw StateError('Must call .init() first.');
    }
    super.send(data);
  }
}

class EmbeddedClient extends FuchsiaSocketClient {
  final Socket _socket;

  EmbeddedClient(this._socket);

  @override
  Future<Null> init() async {
    _reader
      ..bind(_socket)
      ..onReadable = handleRead;
  }
}
