// Copyright 2015 The Vanadium 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:flutter/material.dart';
import 'package:flutter/widgets.dart';

import '../loaders/loader.dart';
import '../models/all.dart' as model;
import '../stores/store.dart';
import '../styles/common.dart' as style;

import 'slidelist.dart';

// DeckGridPage is the full page view of the list of decks.
class DeckGridPage extends StatelessComponent {
  Loader _loader = new Loader.singleton();
  Widget build(BuildContext context) {
    return new Scaffold(
        toolBar: new ToolBar(center: new Text('SyncSlides')),
        floatingActionButton: new FloatingActionButton(
            child: new Icon(icon: 'content/add'), onPressed: () {
          _loader.addDeck();
        }),
        body: new Material(child: new DeckGrid()));
  }
}

// DeckGrid is scrollable grid view of decks.
class DeckGrid extends StatefulComponent {
  _DeckGridState createState() => new _DeckGridState();
}

class _DeckGridState extends State<DeckGrid> {
  Store _store = new Store.singleton();
  List<model.Deck> _decks = new List<model.Deck>();
  StreamSubscription _onDecksChangeSubscription;
  StreamSubscription _onStateChangeSubscription;

  void updateDecks(List<model.Deck> decks) {
    setState(() {
      _decks = decks;
    });
  }

  void _rebuild(_) {
    setState(() {});
  }

  @override
  void initState() {
    // Stop all active presentations when coming back to the decks grid page.
    _store.stopAllPresentations();
    _store.getAllDecks().then(updateDecks);
    // Update the state whenever store tells us decks have changed.
    _onDecksChangeSubscription = _store.onDecksChange.listen(updateDecks);
    _onStateChangeSubscription = _store.onStateChange.listen(_rebuild);
    super.initState();
  }

  @override
  void dispose() {
    // Stop listening to updates from store when component is disposed.
    _onDecksChangeSubscription.cancel();
    _onStateChangeSubscription.cancel();
    super.dispose();
  }

  Widget build(BuildContext context) {
    List<Widget> deckBoxes = _decks.map((deck) => _buildDeckBox(context, deck));
    List<Widget> presentationBoxes = _store.state.livePresentations
        .map((presentation) => _buildPresentationBox(context, presentation));
    var allBoxes = new List.from(presentationBoxes)..addAll(deckBoxes);
    var grid = new Grid(allBoxes, maxChildExtent: style.Size.thumbnailWidth);
    return new ScrollableViewport(child: grid);
  }
}

Widget _buildDeckBox(BuildContext context, model.Deck deckData) {
  var thumbnail = _buildThumbnail(deckData.thumbnail);
  // TODO(aghassemi): Add "Opened on" data.
  var subtitleWidget =
      new Text("Opened on Sep 12, 2015", style: style.Text.subtitleStyle);
  subtitleWidget = _stopWrapping(subtitleWidget);
  var footer = _buildBoxFooter(deckData.name, subtitleWidget);
  var box = _buildCard(deckData.key, [thumbnail, footer], () {
    Navigator.of(context).push(new PageRoute(
        builder: (context) => new SlideListPage(deckData.key, deckData.name)));
  });

  return box;
}

Widget _buildPresentationBox(
    BuildContext context, model.PresentationAdvertisement presentationData) {
  var thumbnail = _buildThumbnail(presentationData.deck.thumbnail);
  var liveBox = new Row([
    new Container(
        child: new Text("LIVE NOW", style: style.Text.liveNow),
        decoration: style.Box.liveNow,
        margin: style.Spacing.normalMargin,
        padding: style.Spacing.extraSmallPadding)
  ]);
  var footer = _buildBoxFooter(presentationData.deck.name, liveBox);
  var box = _buildCard(presentationData.key, [thumbnail, footer], () {});
  return box;
}

// TODO(aghassemi): Cache will be moved to Flutter and will become a map of encoded bytes to
// decoded bytes. This is just a quick work-around for now.
Map<int, RawImage> thumbnailCache = new Map();
Widget _buildThumbnail(List<int> bytes) {
  var key = bytes.hashCode;
  if (thumbnailCache.containsKey(key)) {
    return thumbnailCache[key];
  }
  var thumbnail = new RawImage(bytes: new Uint8List.fromList(bytes));

  thumbnailCache[key] = thumbnail;
  return thumbnail;
}

Widget _buildBoxFooter(String title, Widget subtitle) {
  var titleWidget = new Text(title, style: style.Text.titleStyle);
  titleWidget = _stopWrapping(titleWidget);

  var titleAndSubtitle = new Block([titleWidget, subtitle]);
  return new Container(
      child: titleAndSubtitle, padding: style.Spacing.normalPadding);
}

Widget _buildCard(String key, List<Widget> children, Function onTap) {
  var content = new Container(
      child: new Card(child: new Block(children)),
      margin: style.Spacing.normalMargin);

  return new InkWell(key: new Key(key), child: content, onTap: onTap);
}

Widget _stopWrapping(Text child) {
  // TODO(aghassemi): There is no equivalent of CSS's white-space: nowrap,
  // overflow: hidden or text-overflow: ellipsis in Flutter yet.
  // This workaround simulates white-space: nowrap and overflow: hidden.
  // See https://github.com/flutter/flutter/issues/417
  return new Viewport(
      child: child, scrollDirection: ScrollDirection.horizontal);
}
