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

/// A version of app.dart built on the new async bindings.

import 'dart:async';
import 'package:fidl/fidl.dart';
import 'package:fuchsia/fuchsia.dart';
import 'package:fidl_fuchsia_sys/fidl_async.dart';
import 'package:zircon/zircon.dart';
import 'package:fidl_fuchsia_io/fidl_async.dart';

import 'app.dart' as sync_app;
import 'src/outgoing.dart';

export 'src/outgoing.dart';

/// Deprecated! Use package:fuchsia_services/services.dart instead
class StartupContext {
  static StartupContext _context;

  StartupContext();

  final EnvironmentProxy environment = new EnvironmentProxy();
  final LauncherProxy launcher = new LauncherProxy();
  final ServiceProviderProxy environmentServices = new ServiceProviderProxy();
  final Outgoing outgoingServices = new Outgoing();

  factory StartupContext.fromStartupInfo() {
    if (_context != null) {
      return _context;
    }

    if (sync_app.StartupContext.initialTrace != null) {
      print(
          "WARNING: app.dart's StartupContext was created at:\n${sync_app.StartupContext.initialTrace}");
    }

    final StartupContext context = new StartupContext();

    final Handle environmentHandle = MxStartupInfo.takeEnvironment();
    if (environmentHandle != null) {
      context.environment
        ..ctrl.bind(
            new InterfaceHandle<Environment>(new Channel(environmentHandle)))
        ..getLauncher(context.launcher.ctrl.request())
        ..getServices(context.environmentServices.ctrl.request());
    }

    final Handle outgoingServicesHandle = MxStartupInfo.takeOutgoingServices();
    if (outgoingServicesHandle != null) {
      context.outgoingServices
          .serve(InterfaceRequest<Node>(Channel(outgoingServicesHandle)));
    }

    _context = context;

    return context;
  }

  /// Provide an alternative startup context that will then be provided on
  /// through [StartupContext.fromStartupInfo].
  ///
  /// This is primarily used to provide alternative environment services for
  /// testing purposes.
  static void provideStartupContext(StartupContext context) {
    assert(_context != null, 'StartupContext should never be overwritten.');
    _context = context;
  }

  void close() {
    environment.ctrl.close();
    launcher.ctrl.close();
    environmentServices.ctrl.close();
    outgoingServices.close();
  }
}

/// Deprecated! Use package:fuchsia_services/services.dart instead
Future<void> connectToService<T>(
    ServiceProvider serviceProvider, AsyncProxyController<T> controller) async {
  final String serviceName = controller.$serviceName;
  if (serviceName == null) {
    throw new Exception(
        "${controller.$interfaceName}'s controller.\$serviceName"
        ' must not be null. Check the FIDL file for a missing [Discoverable]');
  }
  await serviceProvider.connectToService(
      serviceName, controller.request().passChannel());
}

/// Deprecated! Use package:fuchsia_services/services.dart instead
InterfaceHandle<T> connectToServiceByName<T>(
    ServiceProvider serviceProvider, String serviceName) {
  final ChannelPair pair = new ChannelPair();
  serviceProvider.connectToService(serviceName, pair.first);
  return new InterfaceHandle<T>(pair.second);
}

typedef ServiceConnector<T> = void Function(InterfaceRequest<T> request);
typedef DefaultServiceConnector<T> = void Function(
    String serviceName, InterfaceRequest<T> request);

typedef _ServiceConnectorThunk = void Function(Channel channel);

/// Deprecated! Use package:fuchsia_services/services.dart instead
class ServiceProviderImpl extends ServiceProvider {
  final ServiceProviderBinding _binding = new ServiceProviderBinding();

  void bind(InterfaceRequest<ServiceProvider> interfaceRequest) {
    _binding.bind(this, interfaceRequest);
  }

  void close() {
    _binding.close();
  }

  DefaultServiceConnector<dynamic> defaultConnector;

  final Map<String, _ServiceConnectorThunk> _connectorThunks =
      <String, _ServiceConnectorThunk>{};

  void addServiceForName<T>(ServiceConnector<T> connector, String serviceName) {
    _connectorThunks[serviceName] = (Channel channel) {
      connector(new InterfaceRequest<T>(channel));
    };
  }

  @override
  Future<Null> connectToService(String serviceName, Channel channel) {
    final _ServiceConnectorThunk connectorThunk = _connectorThunks[serviceName];
    if (connectorThunk != null) {
      connectorThunk(channel);
    } else if (defaultConnector != null) {
      defaultConnector(serviceName, new InterfaceRequest<dynamic>(channel));
    } else {
      channel.close();
    }
    return null;
  }
}

/// Deprecated! Use package:fuchsia_services/services.dart instead
class Services {
  DirectoryProxy _proxy;
  static const int _openFlags =
      openRightReadable | openRightWritable; // connect flags for service
  static const int _openMode = 0x1ED; // 0755

  Services();

  Channel request() {
    _proxy = DirectoryProxy();
    return _proxy.ctrl.request().passChannel();
  }

  Future<void> connectToService<T>(AsyncProxyController<T> controller) async {
    final String serviceName = controller.$serviceName;
    if (serviceName == null) {
      throw new Exception(
          "${controller.$interfaceName}'s controller.\$serviceName"
          ' must not be null. Check the FIDL file for a missing [Discoverable]');
    }
    await _proxy.open(_openFlags, _openMode, serviceName,
        InterfaceRequest<Node>(controller.request().passChannel()));
  }

  Future<InterfaceHandle<T>> connectToServiceByName<T>(
      String serviceName) async {
    final ChannelPair pair = new ChannelPair();

    await _proxy.open(
        _openFlags, _openMode, serviceName, InterfaceRequest<Node>(pair.first));
    return new InterfaceHandle<T>(pair.second);
  }

  Future<void> close() async {
    await _proxy.close();
  }
}
