// 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 '../logic/game.dart'
    show Game, GameType, Viewer, HeartsGame, HeartsPhase;
import '../src/syncbase/syncbase_echo_impl.dart' show SyncbaseEchoImpl;
//import 'board.dart' show Board;
import 'card_collection.dart'
    show CardCollectionComponent, DropType, Orientation;
import 'draggable.dart' show Draggable;

import 'package:sky/widgets.dart';
import 'package:sky/theme/colors.dart' as colors;

abstract class GameComponent extends StatefulComponent {
  Game game;
  Function gameEndCallback;

  GameComponent(this.game, this.gameEndCallback) {
    game.updateCallback = update;
  }

  void update() {
    setState(() {});
  }

  void syncConstructorArguments(GameComponent other) {
    this.game = other.game;
  }

  // A helper that most subclasses use in order to quit their respective games.
  void _quitGameCallback() {
    setState(() {
      this.gameEndCallback();
    });
  }

  Widget _makeButton(String text, Function callback) {
    return new FlatButton(child: new Text(text), onPressed: callback);
  }

  Widget build();
}

GameComponent createGameComponent(Game game, Function gameEndCallback) {
  switch (game.gameType) {
    case GameType.Proto:
      return new ProtoGameComponent(game, gameEndCallback);
    case GameType.Hearts:
      return new HeartsGameComponent(game, gameEndCallback);
    case GameType.SyncbaseEcho:
      return new SyncbaseEchoGameComponent(game, gameEndCallback);
    default:
      // We're probably not ready to serve the other games yet.
      assert(false);
      return null;
  }
}

class ProtoGameComponent extends GameComponent {
  ProtoGameComponent(Game game, Function cb) : super(game, cb);

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

    cardCollections.add(new Text(game.debugString));

    for (int i = 0; i < 4; i++) {
      List<logic_card.Card> cards = game.cardCollections[i];
      CardCollectionComponent c = new CardCollectionComponent(cards,
          game.playerNumber == i, Orientation.horz, _makeGameMoveCallback,
          dragChildren: true, acceptType: DropType.card);
      cardCollections.add(c); // flex
    }

    cardCollections.add(new Container(
        decoration: new BoxDecoration(
            backgroundColor: colors.Green[500], borderRadius: 5.0),
        child: new CardCollectionComponent(game.cardCollections[4], true,
            Orientation.show1, _makeGameMoveCallback,
            dragChildren: true, acceptType: DropType.card)));

    cardCollections.add(_makeDebugButtons());

    return new Container(
        decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
        child: new Flex(cardCollections, direction: FlexDirection.vertical));
  }

  void _makeGameMoveCallback(logic_card.Card card, List<logic_card.Card> dest) {
    setState(() {
      try {
        game.move(card, dest);
      } catch (e) {
        print("You can't do that! ${e.toString()}");
        game.debugString = e.toString();
      }
    });
  }

  Widget _makeDebugButtons() => new Flex([
        new Text('P${game.playerNumber}'),
        _makeButton('Switch View', _switchPlayersCallback),
        _makeButton('Quit', _quitGameCallback)
      ]);

  void _switchPlayersCallback() {
    setState(() {
      game.playerNumber = (game.playerNumber + 1) % 4;
    });
  }
}

class SyncbaseEchoGameComponent extends GameComponent {
  SyncbaseEchoImpl s;

  SyncbaseEchoGameComponent(Game game, Function cb) : super(game, cb);

  Widget build() {
    if (s == null) {
      s = new SyncbaseEchoImpl(game);
    }
    return buildSyncbaseEcho();
  }

  Widget buildSyncbaseEcho() {
    return new Container(
        decoration:
            const BoxDecoration(backgroundColor: const Color(0xFF00ACC1)),
        child: new Flex([
          new RaisedButton(child: new Text('doEcho'), onPressed: s.doEcho),
          new Text('sendMsg: ${s.sendMsg}'),
          new Text('recvMsg: ${s.recvMsg}'),
          new RaisedButton(child: new Text('doPutGet'), onPressed: s.doPutGet),
          new Text('putStr: ${s.putStr}'),
          new Text('getStr: ${s.getStr}'),
          _makeButton('Quit', _quitGameCallback)
        ], direction: FlexDirection.vertical));
  }
}

class HeartsGameComponent extends GameComponent {
  List<logic_card.Card> passingCards = new List<logic_card.Card>();

  HeartsGameComponent(Game game, Function cb) : super(game, cb);
  Widget build() {
    return buildHearts();
    // Does NOT work in checked mode since it has a Stack of Positioned Stack with Positioned Widgets.
    // Issue and possible workaround? https://github.com/domokit/sky_engine/issues/732
    // return new Board(1, [2, 3, 4], [1, 2, 3, 4]);
    // For GameType.Board
  }

  // 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 (dest == passingCards &&
          !passingCards.contains(card) &&
          passingCards.length < 3) {
        passingCards.add(card);
      } else if (dest != passingCards && passingCards.contains(card)) {
        passingCards.remove(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 = this.game as HeartsGame;
    int r = game.getCardSuit(a).compareTo(game.getCardSuit(b));
    if (r != 0) return r;
    return game.getCardValue(a) < game.getCardValue(b) ? -1 : 1;
  }

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

  void _makeGamePassCallback(
      List<logic_card.Card> cards, List<logic_card.Card> dest) {
    setState(() {
      try {
        HeartsGame game = this.game as HeartsGame;
        game.passCards(cards);
        passingCards.clear();
      } catch (e) {
        print("You can't do that! ${e.toString()}");
        game.debugString = e.toString();
      }
    });
  }

  void _makeGameTakeCallback(
      List<logic_card.Card> cards, List<logic_card.Card> dest) {
    setState(() {
      try {
        HeartsGame game = this.game as HeartsGame;
        game.takeCards();
      } catch (e) {
        print("You can't do that! ${e.toString()}");
        game.debugString = e.toString();
      }
    });
  }

  void _makeGameMoveCallback(logic_card.Card card, List<logic_card.Card> dest) {
    setState(() {
      try {
        game.move(card, dest);
      } catch (e) {
        print("You can't do that! ${e.toString()}");
        game.debugString = e.toString();
      }
    });
  }

  void _endRoundDebugCallback() {
    setState(() {
      HeartsGame game = this.game as HeartsGame;
      game.jumpToScorePhaseDebug();
    });
  }

  Widget _makeDebugButtons() => new Flex([
        new Flexible(flex: 1, child: new Text('P${game.playerNumber}')),
        new Flexible(
            flex: 5, child: _makeButton('Switch View', _switchPlayersCallback)),
        new Flexible(
            flex: 5,
            child: _makeButton('Dump Log', () => print(this.game.gamelog))),
        new Flexible(
            flex: 5, child: _makeButton('End Round', _endRoundDebugCallback)),
        new Flexible(flex: 4, child: _makeButton('Quit', _quitGameCallback))
      ]);

  Widget _makeButton(String text, Function callback) {
    return new FlatButton(child: new Text(text), onPressed: callback);
  }

  Widget buildHearts() {
    HeartsGame game = this.game as HeartsGame;

    switch (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 showPlay() {
    HeartsGame game = this.game as HeartsGame;

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

    cardCollections.add(new Text(game.debugString));
    cardCollections.add(new Text("Player ${game.whoseTurn}'s turn"));

    int i = game.playerNumber;
    List<logic_card.Card> cards = game.cardCollections[i];
    CardCollectionComponent c = new CardCollectionComponent(cards,
        game.playerNumber == i, Orientation.suit, _makeGameMoveCallback,
        dragChildren: game.whoseTurn == i, comparator: _compareCards);
    cardCollections.add(c); // flex

    List<Widget> plays = new List<Widget>();
    for (int i = 0; i < 4; i++) {
      DropType t = DropType.none;
      if (game.playerNumber == i) {
        t = DropType.card;
      }
      plays.add(new Container(
          decoration: new BoxDecoration(
              backgroundColor:
                  game.whoseTurn == i ? colors.Blue[500] : colors.Green[500],
              borderRadius: 5.0),
          child: new CardCollectionComponent(
              game.cardCollections[i + HeartsGame.OFFSET_PLAY],
              true,
              Orientation.show1,
              _makeGameMoveCallback,
              acceptType: t)));
    }

    cardCollections.add(new Flex(plays));

    cardCollections.add(_makeDebugButtons());

    return new Container(
        decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
        child: new Flex(cardCollections, direction: FlexDirection.vertical));
  }

  Widget showScore() {
    HeartsGame game = this.game as HeartsGame;

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

    return new Container(
        decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
        child: new Flex([
          new Text('Player ${game.playerNumber}'),
          // TODO(alexfandrianto): we want to show round by round, deltas too, don't we?
          new Text('${game.scores}'),
          w,
          _makeButton("Return to Lobby", _quitGameCallback),
          _makeDebugButtons()
        ], direction: FlexDirection.vertical));
  }

  Widget showDeal() {
    HeartsGame game = this.game as HeartsGame;

    return new Container(
        decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
        child: new Flex([
          new Text('Player ${game.playerNumber}'),
          _makeButton('Deal', game.dealCards),
          _makeDebugButtons()
        ], direction: FlexDirection.vertical));
  }

  Widget showPass() {
    HeartsGame game = this.game as HeartsGame;

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

    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 (!passingCards.contains(c)) {
        remainingCards.add(c);
      }
    });

    bool hasPassed = passCards.length != 0;
    // TODO(alexfandrianto): You can pass as many times as you want... which is silly.
    // Luckily, later passes shouldn't do anything.

    return new Container(
        decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
        child: new Flex(<Widget>[
          new Text(game.debugString),
          new CardCollectionComponent(
              passCards, true, Orientation.horz, _makeGamePassCallback,
              acceptType: DropType.card_collection),
          new Draggable<CardCollectionComponent>(new CardCollectionComponent(
              passingCards, true, Orientation.horz, _uiPassCardCallback,
              dragChildren: !hasPassed, acceptType: DropType.card)),
          new CardCollectionComponent(
              remainingCards, true, Orientation.horz, _uiPassCardCallback,
              dragChildren: !hasPassed, acceptType: DropType.card, comparator: _compareCards),
          _makeDebugButtons()
        ], direction: FlexDirection.vertical));
  }

  Widget showTake() {
    HeartsGame game = this.game as HeartsGame;

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

    bool hasTaken = takeCards.length == 0;

    Widget take = new CardCollectionComponent(
        takeCards, true, Orientation.horz, _makeGameTakeCallback);
    if (!hasTaken) {
      take = new Draggable<CardCollectionComponent>(take);
    }

    return new Container(
        decoration: new BoxDecoration(backgroundColor: colors.Pink[500]),
        child: new Flex(<Widget>[
          new Text(game.debugString),
          take,
          new CardCollectionComponent(
              playerCards, true, Orientation.horz, _makeGameTakeCallback,
              dragChildren: true, acceptType: DropType.card_collection, comparator: _compareCards),
          _makeDebugButtons()
        ], direction: FlexDirection.vertical));
  }
}
