// 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 SolitaireGameComponent extends GameComponent {
  SolitaireGameComponent(Croupier croupier, NoArgCb cb,
      {Key key, double width, double height})
      : super(croupier, cb, key: key, width: width, height: height);

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

class SolitaireGameComponentState
    extends GameComponentState<SolitaireGameComponent> {
  @override
  Widget build(BuildContext context) {
    SolitaireGame game = config.game as SolitaireGame;

    // Build Solitaire and have it fill up the card level map.
    // Unfortunately, this is required so that we can know which card components
    // to collect.
    Widget solitaireWidget = buildSolitaire();

    List<Widget> children = new List<Widget>();
    children.add(new Container(
        decoration: new BoxDecoration(backgroundColor: Colors.grey[300]),
        width: config.width,
        height: config.height,
        child: solitaireWidget));
    if (game.phase == SolitairePhase.Play) {
      // All cards are visible.
      List<int> visibleCardCollectionIndexes =
          game.cardCollections.asMap().keys.toList();

      children.add(this.buildCardAnimationLayer(visibleCardCollectionIndexes));
    }

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

  void _cheatCallback() {
    setState(() {
      SolitaireGame game = config.game as SolitaireGame;
      game.cheatUI();
    });
  }

  void _endRoundDebugCallback() {
    setState(() {
      SolitaireGame game = config.game as SolitaireGame;
      game.jumpToScorePhaseDebug();
    });
  }

  Widget _makeDebugButtons() {
    if (config.game.debugMode == false) {
      return new Flex([
        new Flexible(flex: 4, child: _makeButton('Quit', _quitGameCallback))
      ]);
    }
    return new Container(
        width: config.width,
        child: new Flex([
          new Flexible(
              flex: 1, child: new Text('P${config.game.playerNumber}')),
          new Flexible(flex: 5, child: _makeButton('Cheat', _cheatCallback)),
          new Flexible(
              flex: 5, child: _makeButton('End Round', _endRoundDebugCallback)),
          new Flexible(flex: 4, child: _makeButton('Quit', _quitGameCallback))
        ]));
  }

  @override
  Widget _makeButton(String text, NoArgCb 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 buildSolitaire() {
    SolitaireGame game = config.game as SolitaireGame;

    switch (game.phase) {
      case SolitairePhase.Deal:
        return showDeal();
      case SolitairePhase.Play:
        return showPlay();
      case SolitairePhase.Score:
        return showScore();
      default:
        assert(false);
        return null;
    }
  }

  NoArgCb _makeFlipCallback(int index) {
    SolitaireGame game = config.game as SolitaireGame;
    return () {
      game.flipCardUI(index);
    };
  }

  void _moveCallback(logic_card.Card card, List<logic_card.Card> collection) {
    setState(() {
      SolitaireGame game = config.game;
      String reason = game.canPlay(card, collection);
      if (reason == null) {
        game.move(card, collection);
      } else {
        print("You can't do that! ${reason}");
        game.debugString = reason;
      }
    });
  }

  Widget showPlay() {
    SolitaireGame game = config.game as SolitaireGame;

    double cardSize = config.width / 8.0;

    List<Widget> row1 = new List<Widget>();
    List<CardCollectionComponent> aces = [0, 1, 2, 3].map((int i) {
      return new CardCollectionComponent(
          game.cardCollections[SolitaireGame.OFFSET_ACES + i],
          true,
          CardCollectionOrientation.show1,
          widthCard: cardSize,
          heightCard: cardSize,
          acceptCallback: _moveCallback,
          dragChildren: true,
          acceptType: DropType.card,
          useKeys: true);
    }).toList();
    row1.add(new Row(aces));

    row1.add(new Row([
      new CardCollectionComponent(
          game.cardCollections[SolitaireGame.OFFSET_DISCARD],
          true,
          CardCollectionOrientation.show1,
          widthCard: cardSize,
          heightCard: cardSize,
          dragChildren: true,
          useKeys: true),
      new GestureDetector(
          child: new CardCollectionComponent(
              game.cardCollections[SolitaireGame.OFFSET_DRAW],
              false,
              CardCollectionOrientation.show1,
              widthCard: cardSize,
              heightCard: cardSize,
              useKeys: true),
          onTap: game.canDrawCard ? game.drawCardUI : null),
    ]));

    List<Widget> row2 = new List<Widget>();
    for (int i = 0; i < 7; i++) {
      row2.add(new GestureDetector(
          child: new CardCollectionComponent(
              game.cardCollections[SolitaireGame.OFFSET_DOWN + i],
              false,
              CardCollectionOrientation.show1,
              widthCard: cardSize,
              heightCard: cardSize,
              useKeys: true),
          onTap: game.cardCollections[SolitaireGame.OFFSET_UP + i].length == 0
              ? _makeFlipCallback(i)
              : null));
    }
    List<Widget> row3 = new List<Widget>();
    for (int i = 0; i < 7; i++) {
      row3.add(new CardCollectionComponent(
          game.cardCollections[SolitaireGame.OFFSET_UP + i],
          true,
          CardCollectionOrientation.vert,
          widthCard: cardSize,
          heightCard: cardSize,
          height: config.height * 0.6,
          acceptCallback: _moveCallback,
          dragChildren: true,
          acceptType: DropType.card,
          useKeys: true));
    }

    return new Column([
      new Row(row1, justifyContent: FlexJustifyContent.spaceBetween),
      new Row(row2, justifyContent: FlexJustifyContent.spaceBetween),
      new Row(row3, justifyContent: FlexJustifyContent.spaceBetween),
      _makeDebugButtons()
    ]);
  }

  Widget showScore() {
    SolitaireGame game = config.game as SolitaireGame;

    return new Container(
        decoration: new BoxDecoration(backgroundColor: Colors.pink[500]),
        child: new Flex([
          new Text('Player ${game.playerNumber}'),
          _makeButton("Return to Lobby", _quitGameCallback),
          _makeDebugButtons()
        ], direction: FlexDirection.vertical));
  }

  Widget showDeal() {
    SolitaireGame game = config.game as SolitaireGame;

    return new Container(
        decoration: new BoxDecoration(backgroundColor: Colors.pink[500]),
        child: new Flex([
          new Text('Player ${game.playerNumber}'),
          _makeButton('Deal', game.dealCardsUI),
          _makeDebugButtons()
        ],
            direction: FlexDirection.vertical,
            justifyContent: FlexJustifyContent.spaceBetween));
  }
}
