/// Copyright 2018 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:math' as math;

import 'package:flutter/material.dart';
import 'package:fuchsia_logger/logger.dart';
import 'package:xi_client/client.dart';

import 'document.dart';
import 'editor.dart';
import 'editor_host.dart';

/// Widget that displays multiple editors in a tab view.
class EditorTabs extends EditorHost {
  const EditorTabs({
    @required coreProxy,
    debugBackground = false,
    Key key,
  })  : assert(coreProxy != null),
        super(key: key, coreProxy: coreProxy, debugBackground: debugBackground);

  @override
  State<EditorTabs> createState() => new EditorTabsState();
}

class EditorTabsState extends State<EditorTabs>
    with TickerProviderStateMixin
    implements XiHandler {
  /// the order of views as displayed in tabs
  final List<String> _viewIds = [];

  final Map<String, Document> _documents = {};

  /// We display "Untitled 1" in the tab instead of an internal view id
  final Map<String, String> _fakeDocumentTitles = {};

  int _nextDocumentTitleNumber = 1;

  TabController _tabController;

  @override
  void initState() {
    super.initState();
    widget.coreProxy.handler = this;
    widget.coreProxy.clientStarted().then((_) => newView());
    _tabController = new TabController(vsync: this, length: 0);
  }

  void newView() {
    widget.coreProxy.newView().then((viewId) {
      setState(() {
        _viewIds.add(viewId);
        _fakeDocumentTitles[viewId] = 'Untitled $_nextDocumentTitleNumber';
        _nextDocumentTitleNumber += 1;
        _documents.putIfAbsent(viewId, () => new Document());
        _documents[viewId].finalizeViewProxy(widget.coreProxy.view(viewId));
        int prevIndex = _tabController.index;
        _tabController = new TabController(
            vsync: this, length: _viewIds.length, initialIndex: prevIndex)
          ..animateTo(_viewIds.length - 1);
      });
    });
  }

  void closeView(String viewId) {
    setState(() {
      log.info('closing $viewId, views: $_viewIds');
      widget.coreProxy.closeView(viewId);
      _viewIds.remove(viewId);
      _documents.remove(viewId);
      int prevIndex = _tabController.index;
      _tabController = new TabController(
          vsync: this,
          length: _viewIds.length,
          initialIndex: math.max(0, math.min(prevIndex, _viewIds.length - 1)));
    });
  }

  @override
  XiViewHandler getView(String viewId) {
    // TODO: we create a new document here if one is missing, because this
    // can get called before `newView`'s future resolves. However this does mean
    // races are possible if this is called with a `viewId` of a closed view, in which case
    // we could have some zombie documents sitting around.
    _documents.putIfAbsent(viewId, () => new Document());
    return _documents[viewId];
  }

  @override
  List<List<double>> measureWidths(List<Map<String, dynamic>> args) {
    if (_viewIds.first != null) {
      return _documents[_viewIds.first].measureWidths(args);
    }
    log.warning('measureWidths called with no view');
    return [];
  }

  @override
  void alert(String text) {
    // TODO: show an alert dialog?
    log.warning('core alert: $text');
  }

  @override
  Widget build(BuildContext context) {
    List<Widget> actions = [
      new IconButton(icon: Icon(Icons.add), onPressed: newView)
    ];
    if (_viewIds.length > 1) {
      actions.add(new IconButton(
          icon: Icon(Icons.remove),
          onPressed: () => closeView(_viewIds[_tabController.index])));
    }

    return MaterialApp(
      theme: new ThemeData(
        primaryColor: Colors.pink[300],
      ),
      home: Scaffold(
        appBar: AppBar(
          actions: actions,
          bottom: _viewIds.length > 1
              ? TabBar(
                  indicatorColor: Colors.white,
                  indicatorWeight: 4.0,
                  labelStyle: const TextStyle(fontSize: 16.0),
                  isScrollable: true,
                  controller: _tabController,
                  tabs: _viewIds
                      .map((id) => new Tab(text: _fakeDocumentTitles[id]))
                      .toList(),
                )
              : null,
        ),
        body: makeMainWidget(),
      ),
    );
  }

  Widget makeMainWidget() {
    if (_viewIds.isEmpty) {
      return Container();
    }

    if (_documents.length == 1) {
      return Editor(
          document: _documents[_viewIds[0]],
          key: Key(_viewIds[0]),
          debugBackground: widget.debugBackground);
    }

    return TabBarView(
      physics: const NeverScrollableScrollPhysics(),
      controller: _tabController,
      children: _viewIds.map((id) {
        return new Editor(
          document: _documents[id],
          key: Key(id),
          debugBackground: widget.debugBackground,
        );
      }).toList(),
    );
  }
}
