// 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:developer' show Timeline;

import 'package:fidl/fidl.dart';
import 'package:fidl_fuchsia_cobalt/fidl_async.dart' as cobalt;
import 'package:fidl_fuchsia_modular/fidl_async.dart';
import 'package:fidl_fuchsia_modular_auth/fidl_async.dart';
import 'package:fidl_fuchsia_netstack/fidl_async.dart';
import 'package:fidl_fuchsia_sys/fidl_async.dart';
import 'package:fidl_fuchsia_ui_gfx/fidl_async.dart';
import 'package:fidl_fuchsia_ui_input/fidl_async.dart' as input;
import 'package:fidl_fuchsia_ui_policy/fidl_async.dart';
import 'package:fidl_fuchsia_ui_views/fidl_async.dart';
import 'package:fuchsia_logger/logger.dart';
import 'package:fuchsia_scenic_flutter/child_view_connection.dart'
    show ChildViewConnection;
import 'package:fuchsia_services/services.dart' as app;
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart' show Channel, EventPair;

import 'base_shell_model.dart';
import 'netstack_model.dart';
import 'user_manager.dart';

export 'package:lib.widgets/model.dart'
    show ScopedModel, ScopedModelDescendant, ModelFinder;

/// Function signature for GetPresentationMode callback
typedef GetPresentationModeCallback = void Function(PresentationMode mode);

const Duration _kCobaltTimerTimeout = const Duration(seconds: 20);
const int _kSessionShellLoginTimeMetricId = 14;

// This class is extends the Presentation protocol and implements and PresentationModeListener.
// It delegates the methods to the Presentation received by the CommonBaseShellModel that owns it.
class CommonBaseShellPresentationImpl extends Presentation
    implements PresentationModeListener {
  final CommonBaseShellModel _model;

  CommonBaseShellPresentationImpl(this._model);

  /// |Presentation|.
  @override
  // ignore: avoid_positional_boolean_parameters
  Future<void> enableClipping(bool enabled) async {
    await _model.presentation.enableClipping(enabled);
  }

  @override
  Future<void> useOrthographicView() async {
    await _model.presentation.useOrthographicView();
  }

  @override
  Future<void> usePerspectiveView() async {
    await _model.presentation.usePerspectiveView();
  }

  @override
  Future<void> setRendererParams(List<RendererParam> params) async {
    await _model.presentation.setRendererParams(params);
  }

  @override
  Future<void> setDisplayUsage(DisplayUsage usage) async {
    await _model.presentation.setDisplayUsage(usage);
  }

  @override
  // ignore: avoid_positional_boolean_parameters
  Future<void> setDisplayRotation(
      double displayRotationDegrees, bool animate) async {
    await _model.presentation
        .setDisplayRotation(displayRotationDegrees, animate);
  }

  @override
  Future<void> setDisplaySizeInMm(num widthInMm, num heightInMm) async {
    await _model.presentation.setDisplaySizeInMm(widthInMm, heightInMm);
  }

  @override
  Future<void> captureKeyboardEventHack(input.KeyboardEvent eventToCapture,
      InterfaceHandle<KeyboardCaptureListenerHack> listener) async {
    await _model.presentation
        .captureKeyboardEventHack(eventToCapture, listener);
  }

  @override
  Future<void> capturePointerEventsHack(
      InterfaceHandle<PointerCaptureListenerHack> listener) async {
    await _model.presentation.capturePointerEventsHack(listener);
  }

  @override
  Future<PresentationMode> getPresentationMode() async {
    return await _model.presentation.getPresentationMode();
  }

  @override
  Future<void> setPresentationModeListener(
      InterfaceHandle<PresentationModeListener> listener) async {
    await _model.presentation.setPresentationModeListener(listener);
  }

  /// |PresentationModeListener|.
  @override
  Future<void> onModeChanged() async {
    PresentationMode mode = await getPresentationMode();
    log.info('Presentation mode changed to: $mode');
    switch (mode) {
      case PresentationMode.tent:
        await setDisplayRotation(180.0, true);
        break;
      case PresentationMode.tablet:
        // TODO(sanjayc): Figure out up/down orientation.
        await setDisplayRotation(90.0, true);
        break;
      case PresentationMode.laptop:
      default:
        await setDisplayRotation(0.0, true);
        break;
    }
  }
}

/// Provides common features needed by all base shells.
///
/// This includes user management, presentation handling,
/// and keyboard shortcuts.
class CommonBaseShellModel extends BaseShellModel
    implements
        ServiceProvider,
        KeyboardCaptureListenerHack,
        PointerCaptureListenerHack {
  /// Handles login, logout, and adding/removing users.
  ///
  /// Shouldn't be used before onReady.
  BaseShellUserManager _userManager;

  NetstackModel _netstackModel;

  /// Logs metrics to cobalt.
  final cobalt.Logger logger;

  /// A list of accounts that are already logged in on the device.
  ///
  /// Only updated after [refreshUsers] is called.
  List<Account> _accounts;

  /// Childview connection that contains the session shell.
  ChildViewConnection _childViewConnection;

  final List<KeyboardCaptureListenerHackBinding> _keyBindings = [];

  final PresentationModeListenerBinding _presentationModeListenerBinding =
      PresentationModeListenerBinding();
  final PointerCaptureListenerHackBinding _pointerCaptureListenerBinding =
      PointerCaptureListenerHackBinding();

  // Because this base shell only supports a single user logged in at a time,
  // we don't need to maintain separate ServiceProvider for each logged-in user.
  final ServiceProviderBinding _serviceProviderBinding =
      ServiceProviderBinding();
  final List<PresentationBinding> _presentationBindings =
      <PresentationBinding>[];

  CommonBaseShellPresentationImpl _presentationImpl;

  /// Constructor
  CommonBaseShellModel(this.logger) : super() {
    _presentationImpl = CommonBaseShellPresentationImpl(this);
  }

  List<Account> get accounts => _accounts;

  /// Returns the authenticated child view connection
  ChildViewConnection get childViewConnection => _childViewConnection;
  ChildViewConnection get childViewConnectionNew => _childViewConnection;

  set shouldCreateNewChildView(bool should) {}

  // |ServiceProvider|.
  @override
  Future<void> connectToService(String serviceName, Channel channel) {
    // TODO(SCN-595) mozart.Presentation is being renamed to ui.Presentation.
    if (serviceName == 'ui.Presentation') {
      _presentationBindings.add(PresentationBinding()
        ..bind(_presentationImpl, InterfaceRequest<Presentation>(channel)));
    } else {
      log.warning(
          'UserPickerBaseShell: received request for unknown service: $serviceName !');
      channel.close();
    }

    return null;
  }

  /// Create a new user and login with that user
  Future createAndLoginUser() async {
    try {
      final userId = await _userManager.addUser();
      await login(userId);
    } on UserLoginException catch (ex) {
      log.severe(ex);
    } finally {
      notifyListeners();
    }
  }

  /// Whether or not the device has an internet connection.
  ///
  /// Currently, having an IP is equivalent to having internet, although
  /// this is not completely reliable. This will be always false until
  /// onReady is called.
  bool get hasInternetConnection =>
      _netstackModel?.networkReachable?.value ?? false;

  Future<void> waitForInternetConnection() async {
    if (hasInternetConnection) {
      return null;
    }

    final completer = Completer<void>();

    void listener() {
      if (hasInternetConnection) {
        _netstackModel.removeListener(listener);
        completer.complete();
      }
    }

    _netstackModel.addListener(listener);

    return completer.future;
  }

  /// Login with given user
  Future<void> login(String accountId) async {
    if (_serviceProviderBinding.isBound) {
      log.warning(
        'Ignoring unsupported attempt to log in'
            ' while already logged in!',
      );
      return;
    }

    Timeline.instantSync('logging in', arguments: {'accountId': '$accountId'});
    await logger
        .startTimer(
            _kSessionShellLoginTimeMetricId,
            0,
            '',
            'session_shell_login_timer_id',
            DateTime.now().millisecondsSinceEpoch,
            _kCobaltTimerTimeout.inSeconds)
        .then((status) {
      if (status != cobalt.Status.ok) {
        log.warning(
          'Failed to start timer metric '
              '$_kSessionShellLoginTimeMetricId: $status. ',
        );
      }
    });

    final InterfacePair<ServiceProvider> serviceProvider =
        InterfacePair<ServiceProvider>();

    _serviceProviderBinding.bind(this, serviceProvider.passRequest());

    final viewOwnerHandle =
        _userManager.login(accountId, serviceProvider.passHandle());

    _childViewConnection = ChildViewConnection(
      ViewHolderToken(
          value: EventPair(viewOwnerHandle.passChannel().passHandle())),
      onAvailable: (ChildViewConnection connection) {
        log.info('BaseShell: Child view connection available!');
        connection.requestFocus();
        notifyListeners();
      },
      onUnavailable: (ChildViewConnection connection) {
        log.info('BaseShell: Child view connection now unavailable!');
        onLogout();
        notifyListeners();
      },
    );

    notifyListeners();
  }

  /// Called when the the session shell logs out.
  @mustCallSuper
  Future<void> onLogout() async {
    _childViewConnection = null;
    _serviceProviderBinding.close();
    for (PresentationBinding presentationBinding in _presentationBindings) {
      presentationBinding.close();
    }
    await refreshUsers();
    notifyListeners();
  }

  /// |KeyboardCaptureListener|.
  @override
  Future<void> onEvent(input.KeyboardEvent ev) async {}

  /// |PointerCaptureListener|.
  @override
  Future<void> onPointerEvent(input.PointerEvent event) async {}

  // |BaseShellModel|.
  // TODO: revert to default state when client logs out.
  @mustCallSuper
  @override
  Future<void> onReady(
    UserProvider userProvider,
    BaseShellContext baseShellContext,
    Presentation presentation,
  ) async {
    super.onReady(userProvider, baseShellContext, presentation);

    final netstackProxy = NetstackProxy();
    app.StartupContext.fromStartupInfo()
        .incoming
        .connectToService(netstackProxy);
    _netstackModel = NetstackModel(netstack: netstackProxy)..start();

    await presentation
        .capturePointerEventsHack(_pointerCaptureListenerBinding.wrap(this));
    await presentation.setPresentationModeListener(
        _presentationModeListenerBinding.wrap(_presentationImpl));

    _userManager = BaseShellUserManager(userProvider);

    _userManager.onLogout.listen((_) async {
      await logger
          .endTimer(
              'session_shell_log_out_timer_id',
              DateTime.now().millisecondsSinceEpoch,
              _kCobaltTimerTimeout.inSeconds)
          .then((status) {
        if (status != cobalt.Status.ok) {
          log.warning(
            'Failed to end timer metric '
                'session_shell_log_out_timer_id: $status. ',
          );
        }
      });

      log.info('UserPickerBaseShell: User logged out!');
      await onLogout();
    });

    await refreshUsers();
  }

  // |BaseShellModel|
  // TODO: revert to default state when client logs out.
  @override
  void onStop() {
    for (final binding in _keyBindings) {
      binding.close();
    }
    _presentationModeListenerBinding.close();
    _netstackModel.dispose();
    super.onStop();
  }

  // TODO: revert to default state when client logs out.
  /// Refreshes the list of users.
  Future<void> refreshUsers() async {
    _accounts = List<Account>.from(await _userManager.getPreviousUsers());
    notifyListeners();
  }

  // TODO: revert to default state when client logs out.
  /// Permanently removes the user.
  Future removeUser(Account account) async {
    try {
      await _userManager.removeUser(account.id);
    } on UserLoginException catch (ex) {
      log.severe(ex);
    } finally {
      await refreshUsers();
    }
  }

  @override
  // TODO: implement $serviceData
  ServiceData get $serviceData => null;
}
