// 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 '../logic/card.dart' as logic_card;
import 'card.dart' as component_card;

import 'dart:math' as math;
import 'package:flutter/material.dart';

enum CardCollectionOrientation { vert, horz, fan, show1, suit }
enum DropType {
  none,
  card,
  cardCollection
  // I can see that both would be nice, but I'm not sure how to do that yet.
}

typedef double PosComputer(int index);
typedef void AcceptCb(dynamic data, List<logic_card.Card> cards);

const double DEFAULT_WIDTH = 200.0;
const double DEFAULT_HEIGHT = 200.0;
const double DEFAULT_CARD_HEIGHT = 60.0;
const double DEFAULT_CARD_WIDTH = 60.0;

const double CARD_MARGIN = 3.0; // transparent
const double WHITE_LINE_HEIGHT = 2.0; // white
const double WHITE_LINE_MARGIN = 4.0; // each side

class CardCollectionComponent extends StatefulWidget {
  CardCollectionComponent(this.cards, this.faceUp, this.orientation,
      {this.dragChildren: false,
      this.cardTapCallback: null,
      DropType acceptType,
      this.acceptCallback: null,
      this.comparator: null,
      this.width: DEFAULT_WIDTH,
      this.height: DEFAULT_HEIGHT,
      this.widthCard: DEFAULT_CARD_WIDTH,
      this.heightCard: DEFAULT_CARD_HEIGHT,
      Color backgroundColor,
      Color altColor,
      this.rotation: 0.0,
      this.useKeys: false,
      this.animationType: component_card.CardAnimationType.normal})
      : _acceptType = acceptType,
        _backgroundColor = backgroundColor,
        _altColor = altColor;

  final List<logic_card.Card> cards;
  final CardCollectionOrientation orientation;
  final bool faceUp;
  final AcceptCb acceptCallback;
  final bool dragChildren;
  final component_card.TapCallback cardTapCallback;
  final DropType _acceptType;
  final Comparator<logic_card.Card> comparator;
  final double width;
  final double height;
  final double widthCard;
  final double heightCard;
  final Color _backgroundColor;
  final Color _altColor;
  final double rotation; // This angle is in radians.
  final bool
      useKeys; // If set, every Card created in this collection will be keyed.
  final component_card.CardAnimationType animationType;

  DropType get acceptType => _acceptType ?? DropType.none;
  Color get backgroundColor => _backgroundColor ?? Colors.grey[500];
  Color get altColor => _altColor ?? Colors.grey[500];

  @override
  CardCollectionComponentState createState() {
    return new CardCollectionComponentState();
  }
}

class CardCollectionComponentState extends State<CardCollectionComponent> {
  String status = 'bar';

  bool _handleWillAccept(component_card.Card data) {
    return !config.cards.contains(data.card);
  }

  bool _handleWillAcceptMultiple(CardCollectionComponent data) {
    return data != config; // don't accept your own self.
  }

  void _handleAccept(component_card.Card data) {
    print('accept');
    setState(() {
      status = 'ACCEPT ${data.card.toString()}';
      config.acceptCallback(data.card, config.cards);
    });
  }

  void _handleAcceptMultiple(CardCollectionComponent data) {
    print('acceptMulti');
    setState(() {
      status = 'ACCEPT multi: ${data.cards.toString()}';
      config.acceptCallback(data.cards, config.cards);
    });
  }

  List<logic_card.Card> get _sortedCards {
    assert(config.comparator != null);
    List<logic_card.Card> cs = new List<logic_card.Card>();
    cs.addAll(config.cards);
    cs.sort(config.comparator);
    return cs;
  }

  // returns null if it's up to the container (like a Flex) to figure this out.
  double get desiredHeight {
    switch (config.orientation) {
      case CardCollectionOrientation.vert:
        return config.height;
      case CardCollectionOrientation.horz:
      case CardCollectionOrientation.fan:
      case CardCollectionOrientation.show1:
        return _produceRowHeight;
      case CardCollectionOrientation.suit:
        return _produceRowHeight * 4 + _whiteLineHeight * 3;
      default:
        assert(false);
        return null;
    }
  }

  // returns null if it's up to the container (like a Flex) to figure this out.
  double get desiredWidth {
    switch (config.orientation) {
      case CardCollectionOrientation.vert:
      case CardCollectionOrientation.show1:
        return _produceColumnWidth;
      case CardCollectionOrientation.horz:
      case CardCollectionOrientation.fan:
      case CardCollectionOrientation.suit:
        return config.width;
      default:
        assert(false);
        return null;
    }
  }

  List<Widget> _makeDraggableAndPositioned(
      List<component_card.Card> cardWidgets,
      PosComputer topComputer,
      PosComputer leftComputer) {
    List<Widget> ret = new List<Widget>();
    for (int i = 0; i < cardWidgets.length; i++) {
      Point p = new Point(leftComputer(i), topComputer(i));

      component_card.Card w = cardWidgets[i];
      Widget widgetToAdd = w;
      if (config.dragChildren) {
        widgetToAdd = new Draggable(
            child: w,
            data: w,
            feedback: new Opacity(child: w.clone(visible: true), opacity: 0.5));
      }
      widgetToAdd = new Positioned(left: p.x, top: p.y, child: widgetToAdd);

      ret.add(widgetToAdd);
    }
    return ret;
  }

  double get _produceColumnWidth => config.widthCard + CARD_MARGIN * 2;
  Widget _produceColumn(List<component_card.Card> cardWidgets) {
    double h = config.height ?? config.heightCard * 5;
    double spacing = math.min(config.heightCard + CARD_MARGIN * 2,
        (h - config.heightCard - 2 * CARD_MARGIN) / (cardWidgets.length - 1));

    PosComputer topComputer = (int i) => CARD_MARGIN + spacing * i;
    PosComputer leftComputer = (int i) => CARD_MARGIN;

    List<Widget> draggableKids =
        _makeDraggableAndPositioned(cardWidgets, topComputer, leftComputer);
    return new Container(
        decoration: new BoxDecoration(backgroundColor: config.backgroundColor),
        height: config.height,
        width: _produceColumnWidth,
        child: new Stack(children: draggableKids));
  }

  double get _produceRowHeight => config.heightCard + CARD_MARGIN * 2;
  Widget _produceRow(List<component_card.Card> cardWidgets,
      {emptyBackgroundImage: ""}) {
    if (cardWidgets.length == 0) {
      // Just return a centered background image.
      return new Container(
          decoration:
              new BoxDecoration(backgroundColor: config.backgroundColor),
          height: _produceRowHeight,
          width: config.width,
          child: new Center(child: new Opacity(
              opacity: 0.45,
              child: emptyBackgroundImage == ""
                  ? null
                  : new AssetImage(
                      name: emptyBackgroundImage,
                      fit: ImageFit.scaleDown,
                      height: config.heightCard))));
    }

    double w = config.width ?? config.widthCard * 5;
    double spacing = math.min(config.widthCard + CARD_MARGIN * 2,
        (w - config.widthCard - 2 * CARD_MARGIN) / (cardWidgets.length - 1));

    PosComputer topComputer = (int i) => CARD_MARGIN;
    PosComputer leftComputer = (int i) => CARD_MARGIN + spacing * i;

    List<Widget> draggableKids =
        _makeDraggableAndPositioned(cardWidgets, topComputer, leftComputer);
    return new Container(
        decoration: new BoxDecoration(backgroundColor: config.backgroundColor),
        height: _produceRowHeight,
        width: config.width,
        child: new Stack(children: draggableKids));
  }

  Widget _produceSingle(List<component_card.Card> cardWidgets) {
    PosComputer topComputer = (int i) => CARD_MARGIN;
    PosComputer leftComputer = (int i) => CARD_MARGIN;

    List<Widget> draggableKids =
        _makeDraggableAndPositioned(cardWidgets, topComputer, leftComputer);
    return new Container(
        decoration: new BoxDecoration(backgroundColor: config.backgroundColor),
        height: _produceRowHeight,
        width: _produceColumnWidth,
        child: new Stack(children: draggableKids));
  }

  double get _whiteLineHeight => WHITE_LINE_HEIGHT;

  Widget wrapCards(List<component_card.Card> cardWidgets) {
    switch (config.orientation) {
      case CardCollectionOrientation.vert:
        return _produceColumn(cardWidgets);
      case CardCollectionOrientation.horz:
        return _produceRow(cardWidgets);
      case CardCollectionOrientation.fan:
      // unimplemented, so we'll fall through to show1, for now.
      // Probably a Stack + Positioned
      case CardCollectionOrientation.show1:
        return _produceSingle(cardWidgets);
      case CardCollectionOrientation.suit:
        List<component_card.Card> cs = new List<component_card.Card>();
        List<component_card.Card> ds = new List<component_card.Card>();
        List<component_card.Card> hs = new List<component_card.Card>();
        List<component_card.Card> ss = new List<component_card.Card>();

        List<logic_card.Card> theCards =
            config.comparator != null ? this._sortedCards : config.cards;
        for (int i = 0; i < theCards.length; i++) {
          // Group by suit. Then sort.
          logic_card.Card c = theCards[i];
          switch (c.identifier[0]) {
            case 'c':
              cs.add(cardWidgets[i]);
              break;
            case 'd':
              ds.add(cardWidgets[i]);
              break;
            case 'h':
              hs.add(cardWidgets[i]);
              break;
            case 's':
              ss.add(cardWidgets[i]);
              break;
            default:
              assert(false);
          }
        }
        return new Container(
            decoration: new BoxDecoration(backgroundColor: Colors.white),
            child: new Stack(children: <Widget>[
              new Positioned(
                  top: 2 * _produceRowHeight + 2 * _whiteLineHeight,
                  child: _produceRow(ss,
                      emptyBackgroundImage: "images/suits/Spade.png")),
              new Positioned(
                  top: 3 * _produceRowHeight + 3 * _whiteLineHeight,
                  child: _produceRow(hs,
                      emptyBackgroundImage: "images/suits/Heart.png")),
              new Positioned(
                  top: 0.0,
                  child: _produceRow(cs,
                      emptyBackgroundImage: "images/suits/Club.png")),
              new Positioned(
                  top: _produceRowHeight + _whiteLineHeight,
                  child: _produceRow(ds,
                      emptyBackgroundImage: "images/suits/Diamond.png"))
            ]));
      default:
        assert(false);
        return null;
    }
  }

  @override
  Widget build(BuildContext context) => _buildCollection();

  Widget _buildCollection() {
    List<component_card.Card> cardComponents = new List<component_card.Card>();
    List<logic_card.Card> cs =
        config.comparator != null ? this._sortedCards : config.cards;

    for (int i = 0; i < cs.length; i++) {
      component_card.Card c = new component_card.Card(cs[i], config.faceUp,
          width: config.widthCard,
          height: config.heightCard,
          rotation: config.rotation,
          visible: !config.useKeys,
          useKey: config.useKeys,
          z: 0.0 + i,
          tapCallback: config.cardTapCallback,
          animationType: config.animationType);

      cardComponents.add(c);
    }

    // Let's draw a stack of cards with DragTargets.
    // TODO(alexfandrianto): In many cases, card collections shouldn't have draggable cards.
    // Additionally, it may be worthwhile to restrict it to 1 at a time.
    switch (config.acceptType) {
      case DropType.none:
        return new Container(
            decoration:
                new BoxDecoration(backgroundColor: config.backgroundColor),
            height: this.desiredHeight,
            width: this.desiredWidth,
            child: wrapCards(cardComponents));
      case DropType.card:
        return new DragTarget<component_card.Card>(
            onWillAccept: _handleWillAccept,
            onAccept: _handleAccept,
            builder: (BuildContext context, List<component_card.Card> data, _) {
              return new Container(
                  decoration: new BoxDecoration(backgroundColor: data.isEmpty
                      ? config.backgroundColor
                      : config.altColor),
                  height: this.desiredHeight,
                  width: this.desiredWidth,
                  child: wrapCards(cardComponents));
            });
      case DropType.cardCollection:
        return new DragTarget<CardCollectionComponent>(
            onWillAccept: _handleWillAcceptMultiple,
            onAccept: _handleAcceptMultiple,
            builder:
                (BuildContext context, List<CardCollectionComponent> data, _) {
              return new Container(
                  decoration: new BoxDecoration(backgroundColor: data.isEmpty
                      ? config.backgroundColor
                      : config.altColor),
                  height: this.desiredHeight,
                  width: this.desiredWidth,
                  child: wrapCards(cardComponents));
            });
      default:
        assert(false);
        return null;
    }
  }
}
