// Copyright 2019 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 'package:built_collection/built_collection.dart';
import 'package:flutter/material.dart';
import 'package:fuchsia_scenic_flutter/child_view_connection.dart'
    show ChildViewConnection;
import 'package:tiler/tiler.dart';
import 'package:story_shell_labs_lib/layout/tile_model.dart';
import 'package:story_shell_labs_lib/layout/tile_presenter.dart';

import 'remove_button_target_widget.dart';

final List<Color> _kColors = [
  Colors.red,
  Colors.blue,
  Colors.yellow,
  Colors.green,
  Colors.pink,
  Colors.orange,
  Colors.purple,
];

class StoryWidget extends StatefulWidget {
  final TilePresenter presenter;
  final ValueNotifier<bool> confirmEdit;
  final bool editing;

  const StoryWidget({
    @required this.presenter,
    this.confirmEdit,
    this.editing = false,
  });

  @override
  _StoryWidgetState createState() => _StoryWidgetState();
}

class _StoryWidgetState extends State<StoryWidget> {
  /// Used for resizing locally, moving, etc when in edit mode.
  /// Once out of edit mode, LayoutBloc is notified with the updated model.
  TilerModel<ModuleInfo> _tilerModel;
  BuiltMap<String, ChildViewConnection> _connections;
  StreamSubscription _tilerUpdateListener;
  bool _isEditing = false;
  OverlayEntry _layoutSuggestionsOverlay;
  Map<String, Color> _parametersToColors;
  final ValueNotifier _focusedMod = ValueNotifier<String>(null);

  @override
  void initState() {
    _resetTilerModel();
    _isEditing = widget.editing;
    widget.confirmEdit.addListener(_confirmEditListener);
    _tilerUpdateListener = widget.presenter.update.listen((update) {
      setState(() {
        _isEditing = false;
        _resetTilerModel(update: update);
      });
      updateLayoutSuggestionsOverlayVisibility();
    });
    super.initState();
  }

  @override
  void didUpdateWidget(StoryWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    _isEditing = widget.editing;
    oldWidget.confirmEdit.removeListener(_confirmEditListener);
    widget.confirmEdit.addListener(_confirmEditListener);
  }

  @override
  void dispose() {
    _tilerUpdateListener.cancel();
    super.dispose();
  }

  void _resetTilerModel({TileLayoutModel update}) {
    update ??= widget.presenter.currentState;
    _tilerModel = update.model;
    _connections = update.connections;
    _parametersToColors = _mapFromKeysAndCircularValues(
      _allParametersInModel(_tilerModel),
      _kColors,
    );
  }

  Iterable<ModuleInfo> _flattenTileModel(TileModel tile) => tile == null
      ? []
      : (tile.tiles.expand(_flattenTileModel).toList()..add(tile.content));

  Iterable<String> _allParametersInModel(TilerModel model) =>
      _flattenTileModel(model.root)
          .expand((ModuleInfo content) => content?.parameters ?? <String>[])
          .toSet();

  Map<K, V> _mapFromKeysAndCircularValues<K, V>(
    Iterable<K> keys,
    Iterable<V> values,
  ) =>
      Map.fromIterables(
        keys,
        List.generate(keys.length, (i) => values.elementAt(i % values.length)),
      );

  @override
  Widget build(BuildContext context) {
    return Stack(
      children: <Widget>[
        Positioned.fill(
          child: LayoutPresenter(
            tilerModel: _tilerModel,
            connections: _connections,
            isEditing: _isEditing,
            focusedMod: _focusedMod,
            parametersToColors: _parametersToColors,
            setTilerModel: (model) {
              setState(() {
                _tilerModel = cloneTiler(model);
              });
            },
          ),
        ),
      ],
    );
  }

  void _endEditing() {
    widget.presenter.requestLayout(_tilerModel);
  }

  void _cancelEditing() {
    setState(() {
      _isEditing = false;
      _resetTilerModel();
    });
    updateLayoutSuggestionsOverlayVisibility();
  }

  void _confirmEditListener() {
    if (_isEditing) {
      return;
    }
    if (widget.confirmEdit.value) {
      _endEditing();
    } else {
      _cancelEditing();
    }
  }

  void updateLayoutSuggestionsOverlayVisibility() {
    if (_isEditing && _layoutSuggestionsOverlay == null) {
      _layoutSuggestionsOverlay = OverlayEntry(
        builder: (context) {
          return Positioned(
            left: 0,
            right: 0,
            bottom: 8,
            child: Align(
              alignment: Alignment.bottomCenter,
              child: SizedBox(
                height: 32,
                child: Row(
                  mainAxisAlignment: MainAxisAlignment.center,
                  children: <Widget>[
                    LayoutSuggestionsWidget(
                      presenter: widget.presenter,
                      focusedMod: _focusedMod,
                      onSelect: (model) {
                        setState(() {
                          _tilerModel = cloneTiler(model);
                        });
                      },
                    ),
                    RemoveButtonTargetWidget(
                      onTap: () {
                        getTileContent(_tilerModel)
                            .where((TileModel tile) =>
                                tile.content.modName == _focusedMod.value)
                            .forEach(_tilerModel.remove);
                      },
                    ),
                  ],
                ),
              ),
            ),
          );
        },
      );
      Overlay.of(context).insert(_layoutSuggestionsOverlay);
    }
    if (!_isEditing && _layoutSuggestionsOverlay != null) {
      _layoutSuggestionsOverlay.remove();
      _layoutSuggestionsOverlay = null;
    }
  }
}
