// 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 solitaire;

class SolitaireCommand extends GameCommand {
  // Usually this constructor is used when reading from a log/syncbase.
  SolitaireCommand(String phase, String data)
      : super(phase, data, simultaneity: SimulLevel.TURN_BASED);

  SolitaireCommand.fromCommand(String cmd)
      : super(cmd.split("|")[0], cmd.split("|")[1],
            simultaneity: SimulLevel.TURN_BASED);

  // The following constructors are used for the player generating the SolitaireCommand.
  SolitaireCommand.deal(List<Card> allCards)
      : super("Deal", computeDeal(allCards),
            simultaneity: SimulLevel.TURN_BASED);

  SolitaireCommand.move(Card target, int targetPile)
  : super("Move", computeMove(target, targetPile), simultaneity: SimulLevel.TURN_BASED);

  SolitaireCommand.draw()
  : super("Draw", computeDraw(), simultaneity: SimulLevel.TURN_BASED);

  SolitaireCommand.flip(int targetPile)
  : super("Flip", computeFlip(targetPile), simultaneity: SimulLevel.TURN_BASED);

  static String computeDeal(List<Card> allCards) {
    StringBuffer buff = new StringBuffer();
    allCards.forEach((card) => buff.write("${card.toString()}:"));
    buff.write("END");
    return buff.toString();
  }

  // Note: Depending on the target's position w.r.t. the targetPile, this may
  // actually move a group of cards instead.
  static String computeMove(Card target, int targetPile) {
    return "${target.toString()}:${targetPile}:END";
  }

  // Note: If there are no cards to draw, this will reset the draw pile.
  static String computeDraw() {
    return "END";
  }

  static String computeFlip(int targetPile) {
    return "${targetPile}:END";
  }

  @override
  bool canExecute(Game g) {
    // TODO(alexfandrianto): This is very similar to execute, but without the
    // mutations. It's possible to use a shared function to simplify/combine the
    // logic.
    SolitaireGame game = g as SolitaireGame;

    print("SolitaireCommand is checking: ${data}");
    List<String> parts = data.split(":");
    switch (phase) {
      case "Deal":
        return game.phase == SolitairePhase.Deal && parts.length - 1 == 52;
      case "Move":
        if (game.phase != SolitairePhase.Play) {
          return false;
        }

        // Move the card to the pile.
        Card c = new Card.fromString(parts[0]);
        int targetId = int.parse(parts[1]);
        int sourceId = game.findCard(c);
        if (sourceId == -1) {
          return false;
        }
        List<Card> source = game.cardCollections[sourceId];
        List<Card> dest = game.cardCollections[targetId];

        // If the card isn't valid, then we have an error.
        String reason = game.canPlay(c, dest);
        if (reason != null) {
          return false;
        }
        bool canTransfer = this.transferCheck(source, dest, c);
        return canTransfer;
      case "Draw":
        if (game.phase != SolitairePhase.Play) {
          return false;
        }

        List<Card> drawPile = game.cardCollections[SolitaireGame.OFFSET_DRAW];
        List<Card> discardPile = game.cardCollections[SolitaireGame.OFFSET_DISCARD];

        if (drawPile.length != 0) {
          return this.transferCheck(drawPile, discardPile, drawPile[0]);
        } else if (discardPile.length != 0) {
          return this.transferCheck(discardPile, drawPile, discardPile[0]);
        }
        return false;
      case "Flip":
        if (game.phase != SolitairePhase.Play) {
          return false;
        }

        int flipId = int.parse(parts[0]);
        if (flipId < 0 || flipId > 7) {
          return false;
        }

        List<Card> flipSource = game.cardCollections[SolitaireGame.OFFSET_DOWN + flipId];
        List<Card> flipDest = game.cardCollections[SolitaireGame.OFFSET_UP + flipId];

        if (flipDest.length != 0) {
          return false;
        }
        if (flipSource.length == 0) {
          return false;
        }
        return this.transferCheck(flipSource, flipDest, flipSource[flipSource.length - 1]);
      default:
        print(data);
        assert(false); // How could this have happened?
        return false;
    }
  }

  @override
  void execute(Game g) {
    SolitaireGame game = g as SolitaireGame;

    print("SolitaireCommand is executing: ${data}");
    List<String> parts = data.split(":");
    switch (phase) {
      case "Deal":
        if (game.phase != SolitairePhase.Deal) {
          throw new StateError(
              "Cannot process deal commands when not in Deal phase");
        }
        if (parts.length - 1 != 52) {
          throw new StateError(
            "Not enough cards dealt. Need 52, got ${parts.length - 1}");
        }

        // Deal fills out each of the down cards with one of each up card.
        int index = 0;
        for (int i = 0; i < 7; i++) {
          for (int j = 0; j < i; j++) {
            this.transfer(game.deck, game.cardCollections[SolitaireGame.OFFSET_DOWN + i], new Card.fromString(parts[index]));
            index++;
          }
          this.transfer(game.deck, game.cardCollections[SolitaireGame.OFFSET_UP + i], new Card.fromString(parts[index]));
          index++;
        }

        // The remaining cards are for the draw pile.
        for (; index < 52; index++) {
          this.transfer(game.deck, game.cardCollections[SolitaireGame.OFFSET_DRAW], new Card.fromString(parts[index]));
        }
        return;
      case "Move":
        if (game.phase != SolitairePhase.Play) {
          throw new StateError(
              "Cannot process move commands when not in Play phase");
        }

        // Move the card to the pile.
        Card c = new Card.fromString(parts[0]);
        int targetId = int.parse(parts[1]);
        int sourceId = game.findCard(c);
        if (sourceId == -1) {
          throw new StateError(
            "Cannot move unknown card ${c.toString()}");
        }
        List<Card> source = game.cardCollections[sourceId];
        List<Card> dest = game.cardCollections[targetId];

        // If the card isn't valid, then we have an error.
        String reason = game.canPlay(c, dest);
        if (reason != null) {
          throw new StateError(
              "Cannot move ${c.toString()} to Pile ${targetId} because ${reason}");
        }
        this.transferGroup(source, dest, c);
        return;
      case "Draw":
        if (game.phase != SolitairePhase.Play) {
          throw new StateError(
              "Cannot process draw commands when not in Play phase");
        }

        List<Card> drawPile = game.cardCollections[SolitaireGame.OFFSET_DRAW];
        List<Card> discardPile = game.cardCollections[SolitaireGame.OFFSET_DISCARD];

        if (drawPile.length != 0) {
          this.transfer(drawPile, discardPile, drawPile[0]);
        } else if (discardPile.length != 0) {
          this.transferGroup(discardPile, drawPile, discardPile[0]);
        } else {
          throw new StateError("No cards left to draw");
        }
        return;
      case "Flip":
        if (game.phase != SolitairePhase.Play) {
          throw new StateError(
              "Cannot process flip commands when not in Play phase");
        }

        int flipId = int.parse(parts[0]);
        if (flipId < 0 || flipId > 7) {
          throw new StateError(
            "Cannot process flip command for index ${flipId}");
        }

        List<Card> flipSource = game.cardCollections[SolitaireGame.OFFSET_DOWN + flipId];
        List<Card> flipDest = game.cardCollections[SolitaireGame.OFFSET_UP + flipId];

        if (flipDest.length != 0) {
          throw new StateError(
            "Cannot flip ${flipId} because destination has cards");
        }
        if (flipSource.length == 0) {
          throw new StateError(
            "Cannot flip ${flipId} because source has no cards");
        }
        this.transfer(flipSource, flipDest, flipSource[flipSource.length - 1]);
        return;
      default:
        print(data);
        assert(false); // How could this have happened?
    }
  }

  void transfer(List<Card> sender, List<Card> receiver, Card c) {
    if (!sender.contains(c)) {
      throw new StateError(
          "Sender ${sender.toString()} lacks Card ${c.toString()}");
    }
    sender.remove(c);
    receiver.add(c);
  }

  // Transfers every card from a certain cutoff card onwards.
  void transferGroup(List<Card> sender, List<Card> receiver, Card c) {
    int index = sender.indexOf(c);
    if (index == -1) {
      throw new StateError(
          "Sender ${sender.toString()} lacks Card ${c.toString()}");
    }
    List<Card> lost = new List<Card>.from(sender.getRange(index, sender.length));
    sender.removeRange(index, sender.length);
    receiver.addAll(lost);
  }

  bool transferCheck(List<Card> sender, List<Card> receiver, Card c) {
    return sender.contains(c);
  }
}
