// 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.dart' as cobalt;
import 'package:fidl_fuchsia_modular/fidl.dart';
import 'package:fidl_fuchsia_modular_auth/fidl.dart';
import 'package:fidl_fuchsia_netstack/fidl.dart';
import 'package:fidl_fuchsia_sys/fidl.dart';
import 'package:fidl_fuchsia_ui_gfx/fidl.dart';
import 'package:fidl_fuchsia_ui_input/fidl.dart' as input;
import 'package:fidl_fuchsia_ui_policy/fidl.dart';
import 'package:fuchsia_scenic_flutter/child_view_connection.dart'
    show ChildViewConnection;
import 'package:lib.app.dart/app.dart' as app;
import 'package:lib.app.dart/logging.dart';
import 'package:lib.ui.flutter/child_view.dart' as deprecated
    show ChildViewConnection;
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;

/// Provides common features needed by all base shells.
///
/// This includes user management, presentation handling,
/// and keyboard shortcuts.
class CommonBaseShellModel extends BaseShellModel
    implements
        Presentation,
        ServiceProvider,
        KeyboardCaptureListenerHack,
        PointerCaptureListenerHack,
        PresentationModeListener {
  /// 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.
  bool _shouldCreateNewChildView = false;
  deprecated.ChildViewConnection _deprecatedChildViewConnection;
  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>[];

  /// Constructor
  CommonBaseShellModel(this.logger) : super();

  List<Account> get accounts => _accounts;

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

  set shouldCreateNewChildView(bool should) {
    _shouldCreateNewChildView = should;
  }

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

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

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

  /// 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();
    }
  }

  @override
  // ignore: avoid_positional_boolean_parameters
  void enableClipping(bool enabled) {
    presentation.enableClipping(enabled);
  }

  /// |Presentation|.
  @override
  void getPresentationMode(GetPresentationModeCallback callback) {
    presentation.getPresentationMode(callback);
  }

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

    trace('waiting for internet connection');

    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'});
    logger.startTimer(
      _kSessionShellLoginTimeMetricId,
      0,
      '',
      'session_shell_login_timer_id',
      DateTime.now().millisecondsSinceEpoch,
      _kCobaltTimerTimeout.inSeconds,
      (cobalt.Status 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());

    if (_shouldCreateNewChildView) {
      _childViewConnection = ChildViewConnection.fromViewHolderToken(
        EventPair(viewOwnerHandle.passChannel().passHandle()),
        onAvailable: (ChildViewConnection connection) {
          trace('session shell available');
          log.info('BaseShell: Child view connection available!');
          connection.requestFocus();
          notifyListeners();
        },
        onUnavailable: (ChildViewConnection connection) {
          trace('BaseShell: Child view connection now unavailable!');
          log.info('BaseShell: Child view connection now unavailable!');
          onLogout();
          notifyListeners();
        },
      );
    } else {
      _deprecatedChildViewConnection =
          deprecated.ChildViewConnection.fromViewHolderToken(
        EventPair(viewOwnerHandle.passChannel().passHandle()),
        onAvailable: (deprecated.ChildViewConnection connection) {
          trace('session shell available');
          log.info('BaseShell: Child view connection available!');
          connection.requestFocus();
          notifyListeners();
        },
        onUnavailable: (deprecated.ChildViewConnection connection) {
          trace('BaseShell: Child view connection now unavailable!');
          log.info('BaseShell: Child view connection now unavailable!');
          onLogout();
          notifyListeners();
        },
      );
    }
    notifyListeners();
  }

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

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

  /// |KeyboardCaptureListener|.
  @override
  void onEvent(input.KeyboardEvent ev) {}

  /// |PointerCaptureListener|.
  @override
  void onPointerEvent(input.PointerEvent event) {}

  // |Presentation|.
  // Delegate to the Presentation received by BaseShell.Initialize().
  // 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.connectToService(
        app.StartupContext.fromStartupInfo().environmentServices,
        netstackProxy.ctrl);
    _netstackModel = NetstackModel(netstack: netstackProxy)..start();

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

    _userManager = BaseShellUserManager(userProvider);

    _userManager.onLogout.listen((_) {
      logger.endTimer(
        'session_shell_log_out_timer_id',
        DateTime.now().millisecondsSinceEpoch,
        _kCobaltTimerTimeout.inSeconds,
        (cobalt.Status 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!');
      onLogout();
    });

    await refreshUsers();
  }

  // |Presentation|.
  // Delegate to the Presentation received by BaseShell.Initialize().
  // 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();
  }

  // |Presentation|.
  // Delegate to the Presentation received by BaseShell.Initialize().
  // 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();
  }

  // |Presentation|.
  // Delegate to the Presentation received by BaseShell.Initialize().
  // 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();
    }
  }

  // |Presentation|.
  @override
  // ignore: avoid_positional_boolean_parameters
  void setDisplayRotation(double displayRotationDegrees, bool animate) {
    presentation.setDisplayRotation(displayRotationDegrees, animate);
  }

  // |Presentation|.
  @override
  void setDisplaySizeInMm(num widthInMm, num heightInMm) {
    presentation.setDisplaySizeInMm(widthInMm, heightInMm);
  }

  // |Presentation|.
  @override
  void setDisplayUsage(DisplayUsage usage) {
    presentation.setDisplayUsage(usage);
  }

  // |Presentation|.
  /// |Presentation|.
  @override
  void setPresentationModeListener(
      InterfaceHandle<PresentationModeListener> listener) {
    presentation.setPresentationModeListener(listener);
  }

  // |Presentation|.
  @override
  void setRendererParams(List<RendererParam> params) {
    presentation.setRendererParams(params);
  }

  @override
  void useOrthographicView() {
    presentation.useOrthographicView();
  }

  @override
  void usePerspectiveView() {
    presentation.usePerspectiveView();
  }
}
