// 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.

part of game_component;

class HeartsGameComponent extends GameComponent {
  HeartsGameComponent(Croupier croupier, SoundAssets sounds, VoidCallback cb,
      {Key key, double width, double height})
      : super(croupier, sounds, cb, key: key, width: width, height: height);

  HeartsGame get game => super.game;

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

class HeartsGameComponentState extends GameComponentState<HeartsGameComponent> {
  List<logic_card.Card> passingCards1 = new List<logic_card.Card>();
  List<logic_card.Card> passingCards2 = new List<logic_card.Card>();
  List<logic_card.Card> passingCards3 = new List<logic_card.Card>();
  List<logic_card.Card> bufferedPlay = new List<logic_card.Card>();
  bool bufferedPlaying = false;

  HeartsType _lastViewType;
  bool _showSplitView = false;

  @override
  void initState() {
    super.initState();

    // If someone sat at the table, they would have the value 4.
    // If nobody sat at the table, then we should show the split view.
    if (!_isBoardPresent) {
      _showSplitView = true;
    }
    _reset();
  }

  bool get _isBoardPresent => config.croupier.players_found.values.contains(4);

  @override
  void _reset() {
    super._reset();
    _lastViewType = config.game.viewType;
  }

  bool get _canBuffer {
    HeartsGame game = config.game;
    List<logic_card.Card> playCards =
        game.cardCollections[HeartsGame.offsetPlay + game.playerNumber];
    return game.isPlayer && game.numPlayed >= 1 && playCards.length == 0;
  }

  bool get _shouldUnbuffer {
    HeartsGame game = config.game;
    bool hasPermission = true;
    // TODO(alexfandrianto): https://github.com/vanadium/issues/issues/1098
    // bool hasPermission = game.asking || !_isBoardPresent;
    return game.whoseTurn == game.playerNumber &&
        bufferedPlay.length > 0 &&
        !bufferedPlaying &&
        hasPermission;
  }

  @override
  Widget build(BuildContext context) {
    HeartsGame game = config.game;

    // Reset the game's stored ZCards if the view type changes.
    if (_lastViewType != game.viewType) {
      _reset();
    }

    // If it's our turn and buffered play is not empty, let's play it!
    // Set a flag to ensure that we only play it once.
    if (_shouldUnbuffer) {
      _makeGameMoveCallback(bufferedPlay[0],
          game.cardCollections[HeartsGame.offsetPlay + game.playerNumber]);
      bufferedPlaying = true;
    }

    // If all cards were played, we can safely clear bufferedPlay.
    if (game.allPlayed) {
      _clearBufferedPlay();
    }

    // Hearts Widget
    Widget heartsWidget = new Container(
        decoration: new BoxDecoration(backgroundColor: Colors.grey[300]),
        child: buildHearts());

    List<Widget> children = new List<Widget>();
    children.add(new Container(
        decoration: new BoxDecoration(backgroundColor: Colors.grey[300]),
        width: config.width,
        height: config.height,
        child: heartsWidget));
    List<int> visibleCardCollectionIndexes = new List<int>();
    if (game.phase != HeartsPhase.deal && game.phase != HeartsPhase.score) {
      int playerNum = game.playerNumber;
      if (game.viewType == HeartsType.player) {
        switch (game.phase) {
          case HeartsPhase.pass:
            visibleCardCollectionIndexes.add(HeartsGame.offsetPass + playerNum);
            visibleCardCollectionIndexes.add(HeartsGame.offsetHand + playerNum);
            break;
          case HeartsPhase.take:
            visibleCardCollectionIndexes
                .add(HeartsGame.offsetPass + game.takeTarget);
            visibleCardCollectionIndexes.add(HeartsGame.offsetHand + playerNum);
            break;
          case HeartsPhase.play:
            if (_showSplitView) {
              for (int i = 0; i < 4; i++) {
                visibleCardCollectionIndexes.add(HeartsGame.offsetHand + i);
                visibleCardCollectionIndexes.add(HeartsGame.offsetTrick + i);
                visibleCardCollectionIndexes.add(HeartsGame.offsetPlay + i);
              }
            } else {
              visibleCardCollectionIndexes
                  .add(HeartsGame.offsetPlay + playerNum);
              visibleCardCollectionIndexes
                  .add(HeartsGame.offsetHand + playerNum);
            }

            break;
          default:
            break;
        }
      } else {
        // A board will need to see these things.
        for (int i = 0; i < 4; i++) {
          visibleCardCollectionIndexes.add(HeartsGame.offsetPlay + i);
          visibleCardCollectionIndexes.add(HeartsGame.offsetPass + i);
          visibleCardCollectionIndexes.add(HeartsGame.offsetHand + i);
          visibleCardCollectionIndexes.add(HeartsGame.offsetTrick + i);
        }
      }
    }
    children.add(this.buildCardAnimationLayer(visibleCardCollectionIndexes));

    return new Container(
        width: config.width,
        height: config.height,
        child: new Stack(children: children));
  }

  void _switchViewCallback() {
    HeartsGame game = config.game;
    setState(() {
      if (game.viewType == HeartsType.player) {
        game.viewType = HeartsType.board;
      } else {
        game.viewType = HeartsType.player;
        if (!game.isPlayer) {
          game.playerNumber = 0; // avoid accidental red screen
        }
      }
    });
  }

  // Passing between the temporary pass list and the player's hand.
  // Does not actually move anything in game logic terms.
  void _uiPassCardCallback(logic_card.Card card, List<logic_card.Card> dest) {
    setState(() {
      if (passingCards1.contains(card)) {
        passingCards1.remove(card);
      }
      if (passingCards2.contains(card)) {
        passingCards2.remove(card);
      }
      if (passingCards3.contains(card)) {
        passingCards3.remove(card);
      }

      if (dest == passingCards1) {
        passingCards1.clear();
        passingCards1.add(card);
      } else if (dest == passingCards2) {
        passingCards2.clear();
        passingCards2.add(card);
      } else if (dest == passingCards3) {
        passingCards3.clear();
        passingCards3.add(card);
      }
    });
  }

  int _compareCards(logic_card.Card a, logic_card.Card b) {
    if (a == b) return 0;
    assert(a.deck == "classic" && b.deck == "classic");
    HeartsGame game = config.game;
    int r = game.getCardSuit(a).compareTo(game.getCardSuit(b));
    if (r != 0) return r;
    return game.getCardValue(a) < game.getCardValue(b) ? -1 : 1;
  }

  void _clearPassing() {
    passingCards1.clear();
    passingCards2.clear();
    passingCards3.clear();
  }

  List<logic_card.Card> _combinePassing() {
    List<logic_card.Card> ls = new List<logic_card.Card>();
    ls.addAll(passingCards1);
    ls.addAll(passingCards2);
    ls.addAll(passingCards3);
    return ls;
  }

  void _clearBufferedPlay() {
    bufferedPlay.clear();
    bufferedPlaying = false;
  }

  // This shouldn't always be here, but for now, we have little choice.
  void _switchPlayersCallback() {
    setState(() {
      config.game.playerNumber = (config.game.playerNumber + 1) % 4;
      _clearPassing(); // Just for sanity.
      _clearBufferedPlay();
    });
  }

  void _makeGamePassCallback() {
    setState(() {
      try {
        config.game.passCards(_combinePassing());
        config.game.debugString = null;
        config.sounds.play("whooshOut");
      } catch (e) {
        print("You can't do that! ${e.toString()}");
        config.game.debugString = "You must pass 3 cards";
      }
    });
  }

  void _makeGameTakeCallback() {
    setState(() {
      try {
        // TODO(alexfandrianto): Another way to clear these passing cards is to
        // do so upon the transition from the pass phase to the take phase.
        // However, since they are never seen outside of the Pass phase, it is
        // also valid to clear them upon taking any cards.
        _clearPassing();
        config.game.takeCards();
        config.game.debugString = null;
        config.sounds.play("whooshIn");
      } catch (e) {
        print("You can't do that! ${e.toString()}");
        config.game.debugString = e.toString();
      }
    });
  }

  void _makeGameMoveCallback(logic_card.Card card, List<logic_card.Card> dest) {
    setState(() {
      HeartsGame game = config.game;

      bool isBufferAttempt = dest == bufferedPlay;

      String reason =
          game.canPlay(game.playerNumber, card, lenient: isBufferAttempt);
      if (reason == null) {
        if (isBufferAttempt) {
          print("Buffering ${card}...");
          _clearBufferedPlay();
          bufferedPlay.add(card);
        } else {
          // TODO(alexfandrianto): Clean up soon.
          // https://github.com/vanadium/issues/issues/1098
          // Automatically ask (for when there is no board).
          /*if (!game.asking && !_isBoardPresent) {
            game.askUI();
          }*/
          game.askUI();
          game.move(card, dest);
          config.sounds.play("whooshOut");
        }
        game.debugString = null;
      } else {
        print("You can't do that! ${reason}");
        game.debugString = reason;
      }
    });
  }

  void _makeTakeTrickCallback() {
    HeartsGame game = config.game;
    setState(() {
      game.takeTrickUI();
      game.debugString = null;
      config.sounds.play("whooshIn");
    });
  }

  void _endRoundDebugCallback() {
    setState(() {
      config.game.jumpToScorePhaseDebug();
      config.game.debugString = null;
    });
  }

  Widget _makeDebugButtons() {
    if (config.game.debugMode == false) {
      return new Row(children: [
        new Flexible(flex: 4, child: _makeButton('Quit', _quitGameCallback))
      ]);
    }
    return new Row(children: [
      new Flexible(flex: 1, child: new Text('P${config.game.playerNumber}')),
      new Flexible(
          flex: 5, child: _makeButton('Switch Player', _switchPlayersCallback)),
      new Flexible(
          flex: 5, child: _makeButton('Switch View', _switchViewCallback)),
      new Flexible(
          flex: 5, child: _makeButton('End Round', _endRoundDebugCallback)),
      new Flexible(flex: 4, child: _makeButton('Quit', _quitGameCallback))
    ]);
  }

  @override
  Widget _makeButton(String text, VoidCallback callback,
      {bool inactive: false}) {
    var borderColor = inactive ? Colors.grey[500] : Colors.white;
    var backgroundColor = inactive ? Colors.grey[500] : null;
    return new FlatButton(
        child: new Container(
            decoration: new BoxDecoration(
                border: new Border.all(width: 1.0, color: borderColor),
                backgroundColor: backgroundColor),
            padding: new EdgeDims.all(10.0),
            child: new Text(text)),
        onPressed: inactive ? null : callback);
  }

  Widget buildHearts() {
    if (config.game.viewType == HeartsType.board) {
      return buildHeartsBoard();
    }

    switch (config.game.phase) {
      case HeartsPhase.deal:
        return showDeal();
      case HeartsPhase.pass:
        return showPass();
      case HeartsPhase.take:
        return showTake();
      case HeartsPhase.play:
        return showPlay();
      case HeartsPhase.score:
        return showScore();
      default:
        assert(false);
        return null;
    }
  }

  Widget buildHeartsBoard() {
    List<Widget> kids = new List<Widget>();
    switch (config.game.phase) {
      case HeartsPhase.deal:
      case HeartsPhase.pass:
      case HeartsPhase.take:
      case HeartsPhase.play:
        kids.add(showBoard());
        break;
      case HeartsPhase.score:
        return showScore();
      default:
        assert(false);
        return null;
    }
    kids.add(_makeDebugButtons());
    return new Column(
        children: kids, justifyContent: FlexJustifyContent.spaceBetween);
  }

  Widget showBoard() {
    return new HeartsBoard(config.croupier, config.sounds,
        width: config.width,
        height: 0.825 * config.height, setGameStateCallback: () {
      setState(() {});
    });
  }

  String _getName(int playerNumber) {
    return config.croupier.settingsFromPlayerNumber(playerNumber)?.name;
  }

  HeartsStatus _getStatus() {
    HeartsGame game = config.game;

    String status;
    bool isPlayer = false;
    bool isError = false;
    switch (game.phase) {
      case HeartsPhase.play:
        // Who's turn is it?
        String name = _getName(game.whoseTurn) ?? "Player ${game.whoseTurn}";
        isPlayer = game.whoseTurn == game.playerNumber;
        status = isPlayer ? "Your turn" : "${name}'s turn";

        // Override if someone is taking a trick.
        if (game.allPlayed) {
          int winner = game.determineTrickWinner();
          String trickTaker = _getName(winner) ?? "Player ${winner}";
          isPlayer = winner == game.playerNumber;
          status = isPlayer ? "Your trick" : "${trickTaker}'s trick";
        }
        break;
      case HeartsPhase.pass:
        if (game.hasPassed(game.playerNumber)) {
          status = "Waiting for cards...";
        } else {
          String name =
              _getName(game.passTarget) ?? "Player ${game.passTarget}";
          status = "Pass to ${name}";
          isPlayer = true;
        }
        break;
      case HeartsPhase.take:
        if (game.hasTaken(game.playerNumber)) {
          status = "Waiting for other players...";
        } else {
          String name =
              _getName(game.takeTarget) ?? "Player ${game.takeTarget}";
          status = "Take from ${name}";
          isPlayer = true;
        }
        break;
      default:
        break;
    }

    // Override if there is a debug string.
    if (game.debugString != null) {
      status = game.debugString;
      isError = true;
    }

    return new HeartsStatus(status, isPlayer, isError);
  }

  Widget _buildNumTrickIcon() {
    HeartsGame game = config.game;

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

    String iconName = "image/filter_9_plus";
    if (numTricks == 0) {
      iconName = "image/filter_none";
    } else if (numTricks <= 9) {
      iconName = "image/filter_${numTricks}";
    }

    return new Icon(icon: iconName);
  }

  Widget _buildStatusBar() {
    HeartsGame game = config.game;

    List<Widget> statusBarWidgets = new List<Widget>();
    HeartsStatus status = _getStatus();
    statusBarWidgets.add(new Flexible(
        flex: 1, child: new Text(status.text, style: style.Text.largeStyle)));

    switch (game.phase) {
      case HeartsPhase.play:
        if (game.allPlayed &&
            game.determineTrickWinner() == game.playerNumber &&
            _showSplitView) {
          statusBarWidgets.add(new Flexible(
              flex: 0,
              child: new GestureDetector(
                  onTap: _makeTakeTrickCallback,
                  child: new Container(
                      decoration: style.Box.brightBackground,
                      margin: style.Spacing.smallPaddingSide,
                      padding: style.Spacing.smallPadding,
                      child: new Text("Take Cards",
                          style: style.Text.largeStyle)))));
        }
        statusBarWidgets.add(_buildNumTrickIcon());
        statusBarWidgets
            .add(new IconButton(icon: "action/swap_vert", onPressed: () {
          setState(() {
            _showSplitView = !_showSplitView;
          });
        }));
        break;
      case HeartsPhase.pass:
      case HeartsPhase.take:
        // TODO(alexfandrianto): Icons for arrow_upward and arrow_downward were
        // just added to the material icon list. However, they are not available
        // through Flutter yet.
        double rotationAngle = 0.0; // right
        switch (game.roundNumber % 4) {
          case 1:
            rotationAngle = math.PI; // left
            break;
          case 2:
            rotationAngle = -math.PI / 2; // up
            break;
        }
        if (game.phase == HeartsPhase.take) {
          rotationAngle = rotationAngle + math.PI; // opposite
        }
        statusBarWidgets.add(new Transform(
            transform:
                new vector_math.Matrix4.identity().rotateZ(rotationAngle),
            alignment: new FractionalOffset(0.5, 0.5),
            child: new Icon(icon: "navigation/arrow_forward")));
        break;
      default:
        break;
    }

    BoxDecoration decoration = style.Box.background;
    if (status.isPlayer) {
      decoration = style.Box.liveBackground;
    }
    if (status.isError) {
      decoration = style.Box.errorBackground;
    }

    return new Container(
        padding: new EdgeDims.all(10.0),
        decoration: decoration,
        child: new Row(
            children: statusBarWidgets,
            justifyContent: FlexJustifyContent.spaceBetween));
  }

  Widget _buildFullMiniBoard() {
    return new Container(
        width: config.width * 0.5,
        height: config.height * 0.25,
        child: new HeartsBoard(config.croupier, config.sounds,
            width: config.width * 0.5,
            height: config.height * 0.25,
            cardWidth: config.height * 0.1,
            cardHeight: config.height * 0.1,
            isMini: true,
            gameAcceptCallback: _makeGameMoveCallback,
            bufferedPlay: _canBuffer ? bufferedPlay : null));
  }

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

    List<Widget> cardCollections = new List<Widget>();

    List<logic_card.Card> playOrBuffer =
        game.cardCollections[p + HeartsGame.offsetPlay];
    if (playOrBuffer.length == 0) {
      playOrBuffer = bufferedPlay;
    }

    if (_showSplitView) {
      cardCollections.add(new Container(
          decoration: style.Box.background,
          child: new Column(
              children: [_buildFullMiniBoard(), _buildStatusBar()])));
    } else {
      Widget playArea = new Container(
          decoration: new BoxDecoration(backgroundColor: Colors.teal[500]),
          width: config.width,
          child: new Center(
              child: new CardCollectionComponent(
                  playOrBuffer, true, CardCollectionOrientation.show1,
                  useKeys: true,
                  acceptCallback: _makeGameMoveCallback,
                  acceptType: p == game.whoseTurn || this._canBuffer
                      ? DropType.card
                      : DropType.none,
                  backgroundColor:
                      p == game.whoseTurn ? Colors.white : Colors.grey[500],
                  altColor: p == game.whoseTurn
                      ? Colors.grey[200]
                      : Colors.grey[600])));

      cardCollections.add(new Container(
          decoration: style.Box.background,
          child: new BlockBody(children: [_buildStatusBar(), playArea])));
    }

    List<logic_card.Card> cards = game.cardCollections[p];

    // A buffered card won't show up in the normal hand area.
    List<logic_card.Card> remainingCards = new List<logic_card.Card>();
    cards.forEach((logic_card.Card c) {
      if (!bufferedPlay.contains(c)) {
        remainingCards.add(c);
      }
    });

    // You can start playing/buffering if it's your turn or you can buffer.
    bool canTap = game.whoseTurn == game.playerNumber || this._canBuffer;

    CardCollectionComponent c = new CardCollectionComponent(
        remainingCards, game.playerNumber == p, CardCollectionOrientation.suit,
        dragChildren: true, // Can drag, but may not have anywhere to drop
        cardTapCallback: canTap
            ? (logic_card.Card card) =>
                (_makeGameMoveCallback(card, playOrBuffer))
            : null,
        comparator: _compareCards,
        width: config.width,
        useKeys: true);
    cardCollections.add(new BlockBody(children: [c, _makeDebugButtons()]));

    return new Column(
        children: cardCollections,
        justifyContent: FlexJustifyContent.spaceBetween);
  }

  Widget showScore() {
    HeartsGame game = config.game;

    Widget w;
    if (game.hasGameEnded) {
      w = new Text("Game Over!");
    } else if (!game.isPlayer || game.ready[game.playerNumber]) {
      w = new Text("Waiting for other players...");
    } else {
      w = _makeButton('New Round', game.setReadyUI);
    }

    bool isTall = MediaQuery.of(context).orientation == Orientation.portrait;
    FlexDirection crossDirection =
        isTall ? FlexDirection.horizontal : FlexDirection.vertical;
    FlexDirection mainDirection =
        isTall ? FlexDirection.vertical : FlexDirection.horizontal;
    TextStyle bigStyle = isTall ? style.Text.hugeStyle : style.Text.largeStyle;
    TextStyle bigRedStyle =
        isTall ? style.Text.hugeRedStyle : style.Text.largeRedStyle;

    List<Widget> scores = new List<Widget>();
    scores.add(new Flexible(
        child: new Flex(children: [
          new Flexible(
              child: new Center(child: new Text("Score:", style: bigStyle)),
              flex: 1),
          new Flexible(
              child: new Center(child: new Text("Round", style: bigStyle)),
              flex: 1),
          new Flexible(
              child: new Center(child: new Text("Total", style: bigStyle)),
              flex: 1)
        ], direction: crossDirection),
        flex: 1));
    for (int i = 0; i < 4; i++) {
      bool isMaxForRound =
          game.deltaScores.reduce(math.max) == game.deltaScores[i];
      bool isMaxOverall = game.scores.reduce(math.max) == game.scores[i];

      TextStyle deltaStyle = isMaxForRound ? bigRedStyle : bigStyle;
      TextStyle scoreStyle = isMaxOverall ? bigRedStyle : bigStyle;

      scores.add(new Flexible(
          child: new Flex(children: [
            new Flexible(
                child: new CroupierProfileComponent(
                    settings: config.croupier.settingsFromPlayerNumber(i)),
                flex: 1),
            new Flexible(
                child: new Center(
                    child:
                        new Text("${game.deltaScores[i]}", style: deltaStyle)),
                flex: 1),
            new Flexible(
                child: new Center(
                    child: new Text("${game.scores[i]}", style: scoreStyle)),
                flex: 1)
          ], direction: crossDirection, alignItems: FlexAlignItems.stretch),
          flex: 2));
    }
    return new Column(children: [
      new Flexible(
          child: new Flex(children: scores, direction: mainDirection), flex: 7),
      new Flexible(child: w, flex: 1),
      new Flexible(child: _makeDebugButtons(), flex: 1)
    ]);
  }

  Widget showDeal() {
    return new Container(
        decoration: new BoxDecoration(backgroundColor: Colors.pink[500]),
        child: new Column(children: [
          new Text('Player ${config.game.playerNumber}'),
          new Text('Waiting for Deal...'),
          _makeDebugButtons()
        ], justifyContent: FlexJustifyContent.spaceBetween));
  }

  Widget _helpPassTake(
      String name,
      List<logic_card.Card> c1,
      List<logic_card.Card> c2,
      List<logic_card.Card> c3,
      List<logic_card.Card> hand,
      AcceptCb cb,
      VoidCallback buttoncb) {
    bool completed = (buttoncb == null);
    bool draggable = (cb != null) && !completed;

    List<Widget> topCardWidgets = new List<Widget>();
    AcceptCb topCb = completed ? null : cb;
    topCardWidgets.add(_topCardWidget(c1, topCb));
    topCardWidgets.add(_topCardWidget(c2, topCb));
    topCardWidgets.add(_topCardWidget(c3, topCb));
    topCardWidgets.add(_makeButton(name, buttoncb, inactive: completed));

    Color bgColor = completed ? Colors.teal[600] : Colors.teal[500];

    Widget statusBar = _buildStatusBar();

    Widget topArea = new Container(
        decoration: new BoxDecoration(backgroundColor: bgColor),
        padding: new EdgeDims.all(10.0),
        width: config.width,
        child: new Row(
            children: topCardWidgets,
            justifyContent: FlexJustifyContent.spaceBetween));
    Widget combinedTopArea = new BlockBody(children: [statusBar, topArea]);

    List<logic_card.Card> emptyC;
    if (c1.length == 0) {
      emptyC = c1;
    } else if (c2.length == 0) {
      emptyC = c2;
    } else {
      emptyC = c3; // even if c3 is already filled, it will be replaced.
    }

    Widget handArea = new CardCollectionComponent(
        hand, true, CardCollectionOrientation.suit,
        dragChildren: draggable,
        comparator: _compareCards,
        width: config.width,
        acceptCallback: cb,
        acceptType: draggable ? DropType.card : null,
        cardTapCallback:
            draggable ? (logic_card.Card c) => cb(c, emptyC) : null,
        backgroundColor: Colors.grey[500],
        altColor: Colors.grey[700],
        useKeys: true);

    Widget combinedBottomArea =
        new BlockBody(children: [handArea, _makeDebugButtons()]);

    return new Column(
        children: <Widget>[combinedTopArea, combinedBottomArea],
        justifyContent: FlexJustifyContent.spaceBetween);
  }

  Widget _topCardWidget(List<logic_card.Card> cards, AcceptCb cb) {
    HeartsGame game = config.game;
    List<logic_card.Card> passCards =
        game.cardCollections[game.playerNumber + HeartsGame.offsetPass];

    Widget ccc = new CardCollectionComponent(
        cards, true, CardCollectionOrientation.show1,
        dragChildren: cb != null,
        acceptCallback: cb,
        acceptType: cb != null ? DropType.card : null,
        cardTapCallback:
            cb != null ? (logic_card.Card c) => cb(c, passCards) : null,
        backgroundColor: Colors.white,
        altColor: Colors.grey[200],
        useKeys: true);

    if (cb == null) {
      ccc = new Container(child: ccc);
    }

    return ccc;
  }

  // Pass Phase Screen: Show the cards being passed and the player's remaining cards.
  Widget showPass() {
    HeartsGame game = config.game;

    List<logic_card.Card> passCards =
        game.cardCollections[game.playerNumber + HeartsGame.offsetPass];

    List<logic_card.Card> playerCards = game.cardCollections[game.playerNumber];
    List<logic_card.Card> remainingCards = new List<logic_card.Card>();
    playerCards.forEach((logic_card.Card c) {
      if (!passingCards1.contains(c) &&
          !passingCards2.contains(c) &&
          !passingCards3.contains(c)) {
        remainingCards.add(c);
      }
    });

    bool hasPassed = passCards.length != 0;

    return _helpPassTake(
        "Pass",
        passingCards1,
        passingCards2,
        passingCards3,
        remainingCards,
        _uiPassCardCallback,
        hasPassed ? null : _makeGamePassCallback);
  }

  // Take Phase Screen: Show the cards the player has received and the player's hand.
  Widget showTake() {
    HeartsGame game = config.game;

    List<logic_card.Card> playerCards = game.cardCollections[game.playerNumber];
    List<logic_card.Card> takeCards =
        game.cardCollections[game.takeTarget + HeartsGame.offsetPass];

    bool hasTaken = takeCards.length == 0;

    List<logic_card.Card> take1 =
        takeCards.length != 0 ? takeCards.sublist(0, 1) : [];
    List<logic_card.Card> take2 =
        takeCards.length != 0 ? takeCards.sublist(1, 2) : [];
    List<logic_card.Card> take3 =
        takeCards.length != 0 ? takeCards.sublist(2, 3) : [];

    return _helpPassTake("Take", take1, take2, take3, playerCards, null,
        hasTaken ? null : _makeGameTakeCallback);
  }
}

class HeartsArrangeComponent extends GameArrangeComponent {
  HeartsArrangeComponent(Croupier croupier,
      {double width, double height, Key key})
      : super(croupier, width: width, height: height, key: key);

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

class HeartsArrangeComponentState extends State<HeartsArrangeComponent> {
  bool isTable = null; // Must first ask what kind of device this is.
  bool fallback = false; // Set to true to switch to the old arrange players.

  static final String personIcon = "social/person_outline";
  static final String tableIcon = "hardware/tablet";

  Widget build(BuildContext context) {
    if (isTable == null) {
      return _buildAskDeviceType();
    }
    if (isTable) {
      return _buildTableArrangePlayers();
    }
    if (fallback) {
      return _buildFallbackArrangePlayers();
    }
    return _buildPlayerArrangePlayers();
  }

  Widget _buildAskDeviceType() {
    return new Container(
        decoration: style.Box.liveNow,
        height: config.height,
        width: config.width,
        child: new Column(children: [
          new Text("Play Hearts as a...", style: style.Text.hugeStyle),
          new FlatButton(
              child: new Row(children: [
                new Icon(size: IconSize.s48, icon: personIcon),
                new Text("Player", style: style.Text.largeStyle)
              ], justifyContent: FlexJustifyContent.collapse),
              color: style.secondaryTextColor, onPressed: () {
            setState(() {
              isTable = false;
            });
          }),
          new FlatButton(
              child: new Row(children: [
                new Icon(size: IconSize.s48, icon: tableIcon),
                new Text("Table", style: style.Text.largeStyle)
              ], justifyContent: FlexJustifyContent.collapse),
              color: style.secondaryTextColor, onPressed: () {
            setState(() {
              isTable = true;
            });
            // Also sit at the table.
            config.croupier.settings_manager.setPlayerNumber(
                config.croupier.game.gameID,
                config.croupier.settings.userID,
                4);
          })
        ], alignItems: FlexAlignItems.center));
  }

  int get numSitting => config.croupier.players_found.values.where((int index) {
        return index != null && index >= 0 && index < 4;
      }).length;

  Widget _buildTableArrangePlayers() {
    int arrangeID = null;
    String status = "";
    bool canStart = false;
    if (numSitting < 4) {
      // We still need people to sit.
      // Only include non-table and non-sitting devices in this search.
      // Note that this means it's possible arrangeID is null.
      arrangeID = config.croupier.players_found.keys.firstWhere((int playerID) {
        int index = config.croupier.players_found[playerID];
        return index == null || index < 0;
      }, orElse: () => null);
      status = arrangeID != null ? "Tap to place" : "Waiting for players...";
    } else {
      status = "Play Hearts!";
      canStart = true;
    }

    List<Widget> children = [new Text(status, style: style.Text.hugeStyle)];
    // Also add the player's name (using a placeholder if that's not possible).
    if (arrangeID != null) {
      children.add(new CroupierProfileComponent.textOnly(
          settings: config.croupier.settings_everyone[arrangeID]));
    }

    // You will need to show a Start Game button if the table isn't the creator.
    // Replace the status text with a status button instead.
    if (canStart && !config.croupier.game.isCreator) {
      children = [
        new FlatButton(
            child: new Text(status, style: style.Text.hugeStyle),
            color: style.theme.accentColor, onPressed: () {
          config.croupier.settings_manager
              .setGameStatus(config.croupier.game.gameID, "RUNNING");
        })
      ];
    }
    Widget firstChild = new Row(
        children: children, justifyContent: FlexJustifyContent.collapse);

    return new Container(
        decoration: style.Box.liveNow,
        height: config.height,
        width: config.width,
        child: new Column(children: [
          firstChild,
          new Flexible(child: _buildArrangeTable(activeID: arrangeID))
        ], alignItems: FlexAlignItems.center));
  }

  Widget _buildPlayerArrangePlayers() {
    List<Widget> children = <Widget>[
      new Text("Waiting for game setup...", style: style.Text.hugeStyle)
    ];
    if (config.croupier.game.isCreator) {
      children.add(new FlatButton(
          child: new Text("Manual Setup", style: style.Text.largeStyle),
          color: style.theme.accentColor, onPressed: () {
        setState(() {
          fallback = true;
        });
      }));
    }

    return new Container(
        decoration: style.Box.liveNow,
        height: config.height,
        width: config.width,
        child:
            new Column(children: children, alignItems: FlexAlignItems.center));
  }

  Widget _buildFallbackArrangePlayers() {
    return new Container(
        decoration: style.Box.liveNow,
        height: config.height,
        width: config.width,
        child: _buildArrangeTable(canDragTo: true));
  }

  Widget _buildArrangeTable({int activeID: null, bool canDragTo: false}) {
    int numAtTable = config.croupier.players_found.values
        .where((int playerNumber) => playerNumber == 4)
        .length;
    return new Column(
        children: [
      new Flexible(
          flex: 1,
          child: new Row(
              children: [
            _buildEmptySlot(),
            _buildSlot(personIcon, 2, activeID, canDragTo),
            _buildEmptySlot()
          ],
              justifyContent: FlexJustifyContent.spaceAround,
              alignItems: FlexAlignItems.stretch)),
      new Flexible(
          flex: 1,
          child: new Row(
              children: [
            _buildSlot(personIcon, 1, activeID, canDragTo),
            _buildSlot(tableIcon, 4, activeID, canDragTo,
                extra: "x${numAtTable}"),
            _buildSlot(personIcon, 3, activeID, canDragTo)
          ],
              justifyContent: FlexJustifyContent.spaceAround,
              alignItems: FlexAlignItems.stretch)),
      new Flexible(
          flex: 1,
          child: new Row(
              children: [
            _buildEmptySlot(),
            _buildSlot(personIcon, 0, activeID, canDragTo),
            _buildEmptySlot()
          ],
              justifyContent: FlexJustifyContent.spaceAround,
              alignItems: FlexAlignItems.stretch))
    ],
        justifyContent: FlexJustifyContent.spaceAround,
        alignItems: FlexAlignItems.stretch);
  }

  Widget _buildEmptySlot() {
    return new Flexible(flex: 1, child: new Text(""));
  }

  Widget _buildSlot(String name, int index, int activeID, bool canDragTo,
      {String extra: ""}) {
    Widget slotWidget = new Row(
        children: [
      new Icon(size: IconSize.s48, icon: name),
      new Text(extra, style: style.Text.largeStyle)
    ],
        alignItems: FlexAlignItems.center,
        justifyContent: FlexJustifyContent.center);

    bool isMe = config.croupier.game.playerNumber == index;
    bool isPlayerIndex = index >= 0 && index < 4;
    bool isTableIndex = index == 4;
    bool seatTaken = (isPlayerIndex || (isTableIndex && isMe)) &&
        config.croupier.players_found.containsValue(index);
    if (seatTaken) {
      // Note: If more than 1 person is in the seat, it may no longer show you.
      CroupierSettings cs = config.croupier.settingsFromPlayerNumber(index);
      CroupierProfileComponent cpc =
          new CroupierProfileComponent.horizontal(settings: cs);
      slotWidget =
          new Draggable<CroupierSettings>(child: cpc, feedback: cpc, data: cs);
    }

    Widget dragTarget = new DragTarget<CroupierSettings>(
        builder: (BuildContext context, List<CroupierSettings> data, _) {
      return new GestureDetector(onTap: () {
        if (activeID != null) {
          config.croupier.settings_manager
              .setPlayerNumber(config.croupier.game.gameID, activeID, index);
        }
      },
          child: new Container(
              constraints: const BoxConstraints.expand(),
              decoration: isMe ? style.Box.liveBackground : style.Box.border,
              child: new Center(child: slotWidget)));
    }, onAccept: (CroupierSettings cs) {
      config.croupier.settings_manager
          .setPlayerNumber(config.croupier.game.gameID, cs.userID, index);
    }, onWillAccept: (_) => canDragTo);

    return new Flexible(flex: 1, child: dragTarget);
  }
}

class HeartsStatus {
  final String text;
  final bool isPlayer;
  final bool isError;

  const HeartsStatus(this.text, this.isPlayer, this.isError);
}
