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

import 'package:flutter/material.dart';
import 'package:vector_math/vector_math_64.dart' as vector_math;

import '../logic/card.dart' as logic_card;
import '../logic/croupier.dart' show Croupier;
import '../logic/game/game.dart' show Game, GameType, NoArgCb;
import '../logic/hearts/hearts.dart' show HeartsGame, HeartsPhase;
import '../sound/sound_assets.dart';
import '../styles/common.dart' as style;
import 'card.dart' as component_card;
import 'card_collection.dart'
    show CardCollectionComponent, CardCollectionOrientation, DropType, AcceptCb;
import 'croupier_profile.dart' show CroupierProfileComponent;

const double defaultBoardHeight = 400.0;
const double defaultBoardWidth = 400.0;
const double defaultCardHeight = 40.0;
const double defaultCardWidth = 40.0;

/// A Board represents a fixed-size canvas for drawing a Game's UI.
/// While other Widgets may be drawn to accomodate space, a Board is meant to
/// consume a specific amount of space on the screen, which allows for more
/// control when positioning elements within the Board's area.
abstract class Board extends StatefulComponent {
  final Game game;
  final double _height;
  final double _width;
  final double _cardHeight;
  final double _cardWidth;

  double get height => _height ?? defaultBoardHeight;
  double get width => _width ?? defaultBoardWidth;
  double get cardHeight => _cardHeight ?? defaultCardHeight;
  double get cardWidth => _cardWidth ?? defaultCardWidth;

  Board(this.game,
      {double height, double width, double cardHeight, double cardWidth})
      : _height = height,
        _width = width,
        _cardHeight = cardHeight,
        _cardWidth = cardWidth;
}

/// The HeartsBoard represents the Hearts table view, which shows the number of
/// cards each player has, and the cards they are currently playing.
class HeartsBoard extends Board {
  final Croupier croupier;
  final SoundAssets sounds;
  final bool isMini;
  final AcceptCb gameAcceptCallback;
  final List<logic_card.Card> bufferedPlay;

  HeartsGame get game => super.game;

  HeartsBoard(Croupier croupier, this.sounds,
      {double height,
      double width,
      double cardHeight,
      double cardWidth,
      this.isMini: false,
      this.gameAcceptCallback,
      this.bufferedPlay})
      : super(croupier.game,
            height: height,
            width: width,
            cardHeight: cardHeight,
            cardWidth: cardWidth),
        croupier = croupier {
    assert(this.game is HeartsGame);
  }

  HeartsBoardState createState() => new HeartsBoardState();
}

class HeartsBoardState extends State<HeartsBoard> {
  static const double PROFILE_SIZE = 0.17; // multiplier of config.height

  // Every time the counter changes, a sound will be played.
  // For example, in the pass/take phase, the counter does this:
  // 0->1->2->3->4->3->2->1->0.
  // We play 4 whooshIn sounds followed by 4 whooshOut sounds upon detecting
  // the change. Each sound only occurs during the very first build (the first
  // opportunity to detect the change).
  // In the play phase, we have this instead: 0->1->2->3->4->0
  // This 5-cycle is 4 played cards (whooshIn) and 1 take trick (whooshOut).
  int cardCounter = 0;
  bool passing = true;

  void _handleCardCounterSounds() {
    // Ensure we have the right state while we deal and score.
    if (config.game.phase == HeartsPhase.Deal ||
        config.game.phase == HeartsPhase.Score) {
      cardCounter = 0;
      passing = true;
    }

    // Passing
    if (passing) {
      // If it is now someone's turn, we should no longer be passing.
      if (config.game.whoseTurn != null) {
        passing = false;

        // Special: Play a sound for the last take command of the pass phase.
        if (cardCounter > 0) {
          cardCounter = 0;
          _playSoundOut();
        }
        return;
      }

      // Passing: If somebody passed cards recently...
      if (config.game.numPassed > cardCounter) {
        cardCounter = config.game.numPassed;
        _playSoundIn();
        return;
      }

      // Passing: If somebody took cards recently...
      if (config.game.numPassed < cardCounter) {
        cardCounter = config.game.numPassed;
        _playSoundOut();
        return;
      }
      return;
    }

    // Playing: If somebody played a card...
    if (config.game.numPlayed > cardCounter) {
      cardCounter = config.game.numPlayed;
      _playSoundIn();
      return;
    }

    // Playing: If somebody took the trick...
    if (config.game.numPlayed == 0 && cardCounter != 0) {
      cardCounter = 0;
      _playSoundOut();
    }
  }

  void _playSoundIn() {
    if (!config.isMini) {
      config.sounds.play("whooshIn");
    }
  }

  void _playSoundOut() {
    if (!config.isMini) {
      config.sounds.play("whooshOut");
    }
  }

  Widget build(BuildContext context) {
    double offscreenDelta = config.isMini ? 5.0 : 1.5;

    _handleCardCounterSounds();

    Widget boardChild;
    if (config.game.phase == HeartsPhase.Play) {
      boardChild =
          config.isMini ? _buildMiniBoardLayout() : _buildBoardLayout();
    } else {
      boardChild = _buildPassLayout();
    }

    return new Container(
        height: config.height,
        width: config.width,
        child: new Stack([
          new Positioned(top: 0.0, left: 0.0, child: boardChild),
          new Positioned(
              top: config.height * (offscreenDelta + 0.5),
              left: (config.width - config.cardWidth) / 2,
              child: _buildOffScreenCards(
                  config.isMini ? rotateByGamePlayerNumber(0) : 0)), // bottom
          new Positioned(
              top: (config.height - config.cardHeight) / 2,
              left: config.width * (-offscreenDelta + 0.5),
              child: _buildOffScreenCards(
                  config.isMini ? rotateByGamePlayerNumber(1) : 1)), // left
          new Positioned(
              top: config.height * (-offscreenDelta + 0.5),
              left: (config.width - config.cardWidth) / 2,
              child: _buildOffScreenCards(
                  config.isMini ? rotateByGamePlayerNumber(2) : 2)), // top
          new Positioned(
              top: (config.height - config.cardHeight) / 2,
              left: config.width * (offscreenDelta + 0.5),
              child: _buildOffScreenCards(
                  config.isMini ? rotateByGamePlayerNumber(3) : 3)) // right
        ]));
  }

  int rotateByGamePlayerNumber(int i) {
    return (i + config.game.playerNumber) % 4;
  }

  static Map<int, String> passBackgrounds = const <int, String>{
    0: "images/games/hearts/pass_right.png",
    1: "images/games/hearts/pass_left.png",
    2: "images/games/hearts/pass_across.png",
    3: "",
  };

  Widget _buildPassLayout() {
    String passBackground = ""; // It's possible to have no background.
    if (config.game.phase == HeartsPhase.Pass ||
        config.game.phase == HeartsPhase.Take) {
      passBackground = passBackgrounds[config.game.roundNumber % 4];
    }

    return new Container(
        height: config.height,
        width: config.width,
        child: new Stack([
          new Positioned(
              top: 0.0,
              left: 0.0,
              child: new AssetImage(
                  name: passBackground,
                  height: config.height,
                  width: config.width)),
          new Positioned(top: 0.0, left: 0.0, child: _buildPassLayoutInternal())
        ]));
  }

  double _rotationAngle(int pNum) {
    return pNum * math.PI / 2;
  }

  Widget _rotate(Widget w, int pNum) {
    return new Transform(
        child: w,
        transform:
            new vector_math.Matrix4.identity().rotateZ(_rotationAngle(pNum)),
        alignment: new FractionalOffset(0.5, 0.5));
  }

  Widget _getPass(int playerNumber) {
    double sizeRatio = 0.10;
    double cccSize = math.min(sizeRatio * config.width, config.cardWidth * 3.5);

    HeartsGame game = config.game;
    List<logic_card.Card> cardsToTake = [];
    int takeTarget = game.getTakeTarget(playerNumber);
    if (takeTarget != null) {
      cardsToTake = game.cardCollections[
          game.getTakeTarget(playerNumber) + HeartsGame.OFFSET_PASS];
    }

    bool isHorz = playerNumber % 2 == 0;
    CardCollectionOrientation ori = isHorz
        ? CardCollectionOrientation.horz
        : CardCollectionOrientation.vert;
    return new CardCollectionComponent(cardsToTake, false, ori,
        backgroundColor: style.transparentColor,
        width: isHorz ? cccSize : null,
        height: isHorz ? null : cccSize,
        widthCard: config.cardWidth,
        heightCard: config.cardHeight,
        rotation: playerNumber * math.PI / 2,
        useKeys: true);
  }

  Widget _getProfile(int pNum, double sizeFactor) {
    return new CroupierProfileComponent.horizontal(
        settings: config.croupier.settingsFromPlayerNumber(pNum));
  }

  Widget _playerProfile(int pNum, double sizeFactor) {
    return _rotate(_getProfile(pNum, sizeFactor), pNum);
  }

  Widget _buildPassLayoutInternal() {
    return new Container(
        height: config.height,
        width: config.width,
        child: new Column([
          new Flexible(child: _playerProfile(2, PROFILE_SIZE), flex: 0),
          new Flexible(child: _getPass(2), flex: 0),
          new Flexible(
              child: new Row([
                new Flexible(child: _playerProfile(1, PROFILE_SIZE), flex: 0),
                new Flexible(child: _getPass(1), flex: 0),
                new Flexible(child: new Block([]), flex: 1),
                new Flexible(child: _getPass(3), flex: 0),
                new Flexible(child: _playerProfile(3, PROFILE_SIZE), flex: 0)
              ],
                  alignItems: FlexAlignItems.center,
                  justifyContent: FlexJustifyContent.spaceAround),
              flex: 1),
          new Flexible(child: _getPass(0), flex: 0),
          new Flexible(child: _playerProfile(0, PROFILE_SIZE), flex: 0)
        ],
            alignItems: FlexAlignItems.center,
            justifyContent: FlexJustifyContent.spaceAround));
  }

  Widget _buildMiniBoardLayout() {
    return new Container(
        height: config.height,
        width: config.width,
        child: new Center(
            child: new Row([
          new Flexible(
              flex: 1,
              child: new Center(
                  child: _buildAvatarSlotCombo(rotateByGamePlayerNumber(1)))),
          new Flexible(
              flex: 1,
              child: new Column([
                new Flexible(
                    flex: 1,
                    child: _buildAvatarSlotCombo(rotateByGamePlayerNumber(2))),
                new Flexible(
                    flex: 1,
                    child: _buildAvatarSlotCombo(rotateByGamePlayerNumber(0)))
              ])),
          new Flexible(
              flex: 1,
              child: new Center(
                  child: _buildAvatarSlotCombo(rotateByGamePlayerNumber(3))))
        ])));
  }

  Widget _buildAvatarSlotCombo(int playerNumber) {
    HeartsGame game = config.game;
    int p = game.playerNumber;

    List<Widget> items = new List<Widget>();
    bool isMe = playerNumber == p;

    List<logic_card.Card> showCard =
        game.cardCollections[playerNumber + HeartsGame.OFFSET_PLAY];
    bool hasPlayed = showCard.length > 0;
    bool isTurn = playerNumber == game.whoseTurn && !hasPlayed;
    if (isMe && config.bufferedPlay != null) {
      showCard = config.bufferedPlay;
    }

    items.add(new Positioned(
        top: 0.0,
        left: 0.0,
        child: new CardCollectionComponent(
            showCard, true, CardCollectionOrientation.show1,
            useKeys: true,
            acceptCallback: config.gameAcceptCallback,
            acceptType: isMe && !hasPlayed ? DropType.card : DropType.none,
            widthCard: config.cardWidth - 6.0,
            heightCard: config.cardHeight - 6.0,
            backgroundColor:
                isTurn ? style.theme.accentColor : Colors.grey[500],
            altColor: isTurn ? Colors.grey[200] : Colors.grey[600])));

    if (!hasPlayed) {
      items.add(new Positioned(
          top: 0.0,
          left: 0.0,
          child: new IgnorePointer(
              child: new CroupierProfileComponent.mini(
                  settings:
                      config.croupier.settingsFromPlayerNumber(playerNumber),
                  height: config.cardHeight,
                  width: config.cardWidth))));
    }

    return new Container(
        width: config.cardWidth,
        height: config.cardHeight,
        child: new Stack(items));
  }

  Widget _showTrickText(int pNum) {
    HeartsGame game = config.game;

    int numTrickCards =
        game.cardCollections[HeartsGame.OFFSET_TRICK + pNum].length;
    int numTricks = numTrickCards ~/ 4;

    String s = numTricks != 1 ? "s" : "";

    return _rotate(new Text("${numTricks} trick${s}"), pNum);
  }

  Widget _buildBoardLayout() {
    int activePlayer = config.game.allPlayed
        ? config.game.determineTrickWinner()
        : config.game.whoseTurn;

    // You can tap anywhere on the board to "Ask" or "Take Trick".
    NoArgCb tapCb;
    if (!config.game.asking && !config.game.allPlayed) {
      tapCb = config.game.askUI;
    } else if (config.game.allPlayed) {
      tapCb = config.game.takeTrickUI;
    }

    return new GestureDetector(
        onTap: tapCb,
        child: new Container(
            height: config.height,
            width: config.width,
            decoration: new BoxDecoration(
                border: new Border(
                    top: new BorderSide(
                        color: activePlayer == 2
                            ? style.theme.accentColor
                            : style.transparentColor,
                        width: 5.0),
                    right: new BorderSide(
                        color: activePlayer == 3
                            ? style.theme.accentColor
                            : style.transparentColor,
                        width: 5.0),
                    left: new BorderSide(
                        color: activePlayer == 1
                            ? style.theme.accentColor
                            : style.transparentColor,
                        width: 5.0),
                    bottom: new BorderSide(
                        color: activePlayer == 0
                            ? style.theme.accentColor
                            : style.transparentColor,
                        width: 5.0))),
            child: new Column([
              new Flexible(child: _playerProfile(2, PROFILE_SIZE), flex: 0),
              new Flexible(child: _showTrickText(2), flex: 0),
              new Flexible(
                  child: new Row([
                    new Flexible(
                        child: _playerProfile(1, PROFILE_SIZE), flex: 0),
                    new Flexible(child: _showTrickText(1), flex: 0),
                    new Flexible(
                        child: new Center(child: _buildCenterCards()), flex: 1),
                    new Flexible(child: _showTrickText(3), flex: 0),
                    new Flexible(
                        child: _playerProfile(3, PROFILE_SIZE), flex: 0)
                  ],
                      alignItems: FlexAlignItems.center,
                      justifyContent: FlexJustifyContent.spaceAround),
                  flex: 1),
              new Flexible(child: _showTrickText(0), flex: 0),
              new Flexible(child: _playerProfile(0, PROFILE_SIZE), flex: 0)
            ],
                alignItems: FlexAlignItems.center,
                justifyContent: FlexJustifyContent.spaceAround)));
  }

  Widget _buildCenterCards() {
    //bool wide = (config.width >= config.height);

    double height = config.cardHeight * this._centerScaleFactor;
    double width = config.cardWidth * this._centerScaleFactor;
    Widget centerPiece =
        new Container(height: height, width: width, child: new Block([]));
    if (config.game.allPlayed) {
      int rotateNum = config.game.determineTrickWinner();

      centerPiece = _rotate(
          new Container(
              height: height,
              width: width,
              child: new RaisedButton(
                  child: new Text("Take", style: style.Text.largeStyle),
                  onPressed: config.game.takeTrickUI,
                  color: style.theme.accentColor)),
          rotateNum);
    }

    return new Column([
      new Flexible(
          child: new Row([
        new Flexible(child: new Block([])),
        new Flexible(child: new Center(child: _buildCenterCard(2))),
        new Flexible(child: new Block([])),
      ],
              alignItems: FlexAlignItems.center,
              justifyContent: FlexJustifyContent.center)),
      new Flexible(
          child: new Row([
        new Flexible(child: new Center(child: _buildCenterCard(1))),
        new Flexible(child: new Block([centerPiece])),
        new Flexible(child: new Center(child: _buildCenterCard(3))),
      ],
              alignItems: FlexAlignItems.center,
              justifyContent: FlexJustifyContent.center)),
      new Flexible(
          child: new Row([
        new Flexible(child: new Block([])),
        new Flexible(child: new Center(child: _buildCenterCard(0))),
        new Flexible(child: new Block([])),
      ],
              alignItems: FlexAlignItems.center,
              justifyContent: FlexJustifyContent.center))
    ],
        alignItems: FlexAlignItems.center,
        justifyContent: FlexJustifyContent.center);
  }

  double get _centerScaleFactor {
    bool wide = (config.width >= config.height);
    double heightUsed = 2 * PROFILE_SIZE;

    if (wide) {
      return config.height * (1 - heightUsed) / (config.cardHeight * 4);
    } else {
      return (config.width - (1.5 * config.height * heightUsed)) /
          (config.cardWidth * 4);
    }
  }

  Widget _buildCenterCard(int playerNumber) {
    HeartsGame game = config.game;
    List<logic_card.Card> cards =
        game.cardCollections[playerNumber + HeartsGame.OFFSET_PLAY];

    bool hasPlayed = cards.length > 0;
    bool isTurn = game.whoseTurn == playerNumber && !hasPlayed;

    double height = config.cardHeight * this._centerScaleFactor;
    double width = config.cardWidth * this._centerScaleFactor;

    List<Widget> stackWidgets = <Widget>[
      new Positioned(
          top: 0.0,
          left: 0.0,
          child: new CardCollectionComponent(
              cards, true, CardCollectionOrientation.show1,
              widthCard: width - 6,
              heightCard: height - 6,
              rotation: _rotationAngle(playerNumber),
              useKeys: true))
    ];

    if (isTurn) {
      stackWidgets.add(new Positioned(
          top: 0.0,
          left: 0.0,
          child: _rotate(
              new Container(
                  height: height,
                  width: width,
                  child: new RaisedButton(
                      child: new Text("Play", style: style.Text.largeStyle),
                      onPressed: config.game.asking ? null : config.game.askUI,
                      color: style.theme.accentColor)),
              playerNumber)));
    }

    return new Container(
        height: height, width: width, child: new Stack(stackWidgets));
  }

  // The off-screen cards consist of trick cards and play cards.
  // When the board is mini, the player's play cards are excluded.
  Widget _buildOffScreenCards(int playerNumber) {
    HeartsGame game = config.game;

    List<logic_card.Card> cards = new List.from(
        game.cardCollections[playerNumber + HeartsGame.OFFSET_TRICK]);

    bool isPlay = game.phase == HeartsPhase.Play;

    // Prevent over-expansion of cards until a card has been played.
    bool alreadyPlaying =
        (isPlay && (game.numPlayed > 0 || game.trickNumber > 0));

    double sizeFactor = 1.0;
    if (config.isMini) {
      if (playerNumber != game.playerNumber) {
        cards.addAll(
            game.cardCollections[playerNumber + HeartsGame.OFFSET_HAND]);
      }
    } else {
      cards.addAll(game.cardCollections[playerNumber + HeartsGame.OFFSET_HAND]);

      if (alreadyPlaying) {
        sizeFactor = this._centerScaleFactor;
      }
    }

    return new CardCollectionComponent(
        cards, alreadyPlaying, CardCollectionOrientation.show1,
        widthCard: config.cardWidth * sizeFactor,
        heightCard: config.cardHeight * sizeFactor,
        useKeys: true,
        rotation: config.isMini ? null : _rotationAngle(playerNumber),
        animationType: component_card.CardAnimationType.LONG);
  }
}
