// 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 'package:fidl_fuchsia_cobalt/fidl_async.dart' as cobalt;
import 'package:fidl_fuchsia_mem/fidl_async.dart';
import 'package:fidl_fuchsia_netstack/fidl_async.dart';
import 'package:flutter/material.dart';
import 'package:fuchsia_logger/logger.dart';
import 'package:fuchsia_services/services.dart';
import 'package:lib.base_shell/base_shell_widget.dart';
import 'package:lib.base_shell/netstack_model.dart';
import 'package:lib.widgets/application.dart';
import 'package:lib.widgets/model.dart';
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart';

import 'authentication_overlay.dart';
import 'authentication_overlay_model.dart';
import 'authentication_ui_context_impl.dart';
import 'user_picker_base_shell_model.dart';
import 'user_picker_base_shell_screen.dart';

const double _kMousePointerElevation = 800.0;
const double _kIndicatorElevation = _kMousePointerElevation - 1.0;

const String _kCobaltConfigBinProtoPath = '/pkg/data/sysui_metrics_config.pb';

/// The main base shell widget.
BaseShellWidget<UserPickerBaseShellModel> _baseShellWidget;

void main() {
  setupLogger(name: 'userpicker_base_shell');
  StartupContext startupContext = StartupContext.fromStartupInfo();

  // Connect to Cobalt
  cobalt.LoggerProxy logger = cobalt.LoggerProxy();

  cobalt.LoggerFactoryProxy loggerFactory = cobalt.LoggerFactoryProxy();
  StartupContext.fromStartupInfo().incoming.connectToService(loggerFactory);

  SizedVmo configVmo = SizedVmo.fromFile(_kCobaltConfigBinProtoPath);
  cobalt.ProjectProfile profile = cobalt.ProjectProfile(
      config: Buffer(vmo: configVmo, size: configVmo.size),
      releaseStage: cobalt.ReleaseStage.ga);
  loggerFactory
      .createLogger(profile, logger.ctrl.request())
      .then((cobalt.Status s) {
    if (s != cobalt.Status.ok) {
      print('Failed to obtain Logger. Cobalt config is invalid.');
    }
  });
  loggerFactory.ctrl.close();

  NetstackProxy netstackProxy = NetstackProxy();
  StartupContext.fromStartupInfo().incoming.connectToService(netstackProxy);

  NetstackModel netstackModel = NetstackModel(netstack: netstackProxy)
    ..start();

  _OverlayModel wifiInfoOverlayModel = _OverlayModel();

  final AuthenticationOverlayModel authModel = AuthenticationOverlayModel();

  UserPickerBaseShellModel userPickerBaseShellModel =
      UserPickerBaseShellModel(
    onBaseShellStopped: () {
      netstackProxy.ctrl.close();
      netstackModel.dispose();
    },
    onLogin: () {
      wifiInfoOverlayModel.showing = false;
    },
    onWifiTapped: () {
      wifiInfoOverlayModel.showing = !wifiInfoOverlayModel.showing;
    },
    logger: logger,
  );

  Widget mainWidget = Stack(
    fit: StackFit.passthrough,
    children: <Widget>[
      UserPickerBaseShellScreen(
        launcher: startupContext.launcher,
      ),
      ScopedModel<AuthenticationOverlayModel>(
        model: authModel,
        child: AuthenticationOverlay(),
      ),
    ],
  );

  Widget app = mainWidget;

  List<OverlayEntry> overlays = <OverlayEntry>[
    OverlayEntry(
      builder: (BuildContext context) => MediaQuery(
            data: MediaQueryData(),
            child: FocusScope(
              node: FocusScopeNode(),
              autofocus: true,
              child: app,
            ),
          ),
    ),
    OverlayEntry(
      builder: (BuildContext context) => ScopedModel<_OverlayModel>(
            model: wifiInfoOverlayModel,
            child: _WifiInfo(
              wifiWidget: ApplicationWidget(
                url:
                    'fuchsia-pkg://fuchsia.com/wifi_settings#meta/wifi_settings.cmx',
                launcher: startupContext.launcher,
              ),
            ),
          ),
    ),
  ];

  _baseShellWidget = BaseShellWidget<UserPickerBaseShellModel>(
    startupContext: startupContext,
    baseShellModel: userPickerBaseShellModel,
    authenticationUiContext: AuthenticationUiContextImpl(
        onStartOverlay: authModel.onStartOverlay,
        onStopOverlay: authModel.onStopOverlay),
    child: LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) =>
          (constraints.biggest == Size.zero)
              ? const Offstage()
              : ScopedModel<NetstackModel>(
                  model: netstackModel,
                  child: Overlay(initialEntries: overlays),
                ),
    ),
  );

  runApp(_baseShellWidget);

  _baseShellWidget.advertise();
}

class _WifiInfo extends StatelessWidget {
  final Widget wifiWidget;

  const _WifiInfo({@required this.wifiWidget}) : assert(wifiWidget != null);

  @override
  Widget build(BuildContext context) =>
      ScopedModelDescendant<_OverlayModel>(
        builder: (
          BuildContext context,
          Widget child,
          _OverlayModel model,
        ) =>
            Offstage(
              offstage: !model.showing,
              child: Stack(
                children: <Widget>[
                  Listener(
                    behavior: HitTestBehavior.opaque,
                    onPointerDown: (PointerDownEvent event) {
                      model.showing = false;
                    },
                  ),
                  Center(
                    child: FractionallySizedBox(
                      widthFactor: 0.75,
                      heightFactor: 0.75,
                      child: Container(
                        margin: EdgeInsets.all(8.0),
                        child: PhysicalModel(
                          color: Colors.grey[900],
                          elevation: _kIndicatorElevation,
                          borderRadius: BorderRadius.circular(8.0),
                          child: wifiWidget,
                        ),
                      ),
                    ),
                  ),
                ],
              ),
            ),
      );
}

class _OverlayModel extends Model {
  bool _showing = false;

  set showing(bool showing) {
    if (_showing != showing) {
      _showing = showing;
      notifyListeners();
    }
  }

  bool get showing => _showing;
}
