// 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 = new StartupContext.fromStartupInfo();

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

  cobalt.LoggerFactoryProxy loggerFactory = new 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 = new NetstackProxy();
  StartupContext.fromStartupInfo().incoming.connectToService(netstackProxy);

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

  _OverlayModel wifiInfoOverlayModel = new _OverlayModel();

  final AuthenticationOverlayModel authModel = AuthenticationOverlayModel();

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

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

  Widget app = mainWidget;

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

  _baseShellWidget = new BaseShellWidget<UserPickerBaseShellModel>(
    startupContext: startupContext,
    baseShellModel: userPickerBaseShellModel,
    authenticationUiContext: new AuthenticationUiContextImpl(
        onStartOverlay: authModel.onStartOverlay,
        onStopOverlay: authModel.onStopOverlay),
    child: new LayoutBuilder(
      builder: (BuildContext context, BoxConstraints constraints) =>
          (constraints.biggest == Size.zero)
              ? const Offstage()
              : new ScopedModel<NetstackModel>(
                  model: netstackModel,
                  child: new 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) =>
      new ScopedModelDescendant<_OverlayModel>(
        builder: (
          BuildContext context,
          Widget child,
          _OverlayModel model,
        ) =>
            new Offstage(
              offstage: !model.showing,
              child: new Stack(
                children: <Widget>[
                  new Listener(
                    behavior: HitTestBehavior.opaque,
                    onPointerDown: (PointerDownEvent event) {
                      model.showing = false;
                    },
                  ),
                  new Center(
                    child: new FractionallySizedBox(
                      widthFactor: 0.75,
                      heightFactor: 0.75,
                      child: new Container(
                        margin: const EdgeInsets.all(8.0),
                        child: new PhysicalModel(
                          color: Colors.grey[900],
                          elevation: _kIndicatorElevation,
                          borderRadius: new 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;
}
