// 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:fuchsia_logger/logger.dart';
import 'package:fuchsia_services/services.dart' as app;
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart' show Channel;

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 = 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. May be null, in which case no metrics are logged.
  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;

  final List<KeyboardCaptureListenerHackBinding> _keyBindings = [];

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

  final List<PresentationBinding> _presentationBindings =
      <PresentationBinding>[];

  CommonBaseShellPresentationImpl _presentationImpl;

  /// Has the user logged in or not yet?
  bool _loggedIn = false;

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

  List<Account> get accounts => _accounts;

  // |ServiceProvider|.
  @override
  Future<void> connectToService(String serviceName, Channel channel) {
    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 (_loggedIn) {
      log.warning(
        'Ignoring unsupported attempt to log in while already logged in!',
      );
      return;
    }

    Timeline.instantSync('logging in', arguments: {'accountId': '$accountId'});
    
    if (logger != null) {
      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. ',
            );
          }
      });
    }

    _userManager.login(accountId);
    _loggedIn = true;

    notifyListeners();
  }

  /// Called when the the session shell logs out.
  @mustCallSuper
  Future<void> onLogout() async {
    _loggedIn = false;

    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 {
        if (logger != null) {
          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;
}
