package extend.zp.uitl;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Stack;

import extend.zp.EXPlayer;
import extend.zp.RuleWeight;

public class WinCard {
	public int					pair_count;
	public int					long_count;
	public Stack<List<Integer>>	stack;
	public Stack<Integer>		stackHuxi;
	public List<Integer>		cardList;

	private void push(List<Integer> cardGroup) {
		this.stack.push(cardGroup);
	}

	private void rollBack() {
		List<Integer> cardGroup = this.stack.pop();
		for (Integer card : cardGroup) {
			this.cardList.add(card);
		}
		Collections.sort(this.cardList);
	}

	private boolean tryKezi(int card, EXPlayer player) {
		if (CardUtil.cardNum(card, this.cardList) >= 3) {
			CardUtil.removeCard(this.cardList, card, 3);
			List<Integer> cardGroup = new ArrayList<Integer>();
			cardGroup.add(card);
			cardGroup.add(card);
			cardGroup.add(card);
			this.push(cardGroup);
			int huXi = 0;
			if (player.getRoom().isTianHu && card == player.getRoom().drawCard && player.getRoom().bankerSeat == player.seat) {
				huXi = Paixing.caclHuxi(RuleWeight.TYPE_KAN, card);
			} else {
				huXi = Paixing.caclHuxi(RuleWeight.TYPE_PONG, card);
			}
			player.huXi += huXi;
			this.stackHuxi.push(huXi);
			return true;
		}
		return false;
	}

	private boolean tryShunzi1(int card, EXPlayer player) {
		if (card < 200 && card % 100 > 8) {
			return false;
		}
		if (CardUtil.cardNum(card + 1, this.cardList) > 0 && CardUtil.cardNum(card + 2, this.cardList) > 0) {
			CardUtil.removeCard(this.cardList, card, 1);
			CardUtil.removeCard(this.cardList, card + 1, 1);
			CardUtil.removeCard(this.cardList, card + 2, 1);
			List<Integer> cardGroup = new ArrayList<Integer>();
			cardGroup.add(card);
			cardGroup.add(card + 1);
			cardGroup.add(card + 2);
			this.push(cardGroup);

			int huXi = 0;
			if (card % 100 == 1) {
				huXi = Paixing.caclHuxi(RuleWeight.TYPE_CHOW, card);
				player.huXi += huXi;
			}
			this.stackHuxi.push(huXi);
			return true;
		}
		return false;
	}

	private boolean tryShunzi2(int card) {
		if (CardUtil.cardType(card) == RuleWeight.SMALL_CARD) {
			if (CardUtil.cardNum(card + 100, this.cardList) >= 1 && CardUtil.cardNum(card, this.cardList) >= 2) {
				CardUtil.removeCard(this.cardList, card, 2);
				CardUtil.removeCard(this.cardList, card + 100, 1);
				List<Integer> cardGroup = new ArrayList<Integer>();
				cardGroup.add(card);
				cardGroup.add(card);
				cardGroup.add(card + 100);
				this.push(cardGroup);
				this.stackHuxi.push(0);
				return true;
			}
			if (CardUtil.cardNum(card + 100, this.cardList) >= 2) {
				CardUtil.removeCard(this.cardList, card, 1);
				CardUtil.removeCard(this.cardList, card + 100, 2);
				List<Integer> cardGroup = new ArrayList<Integer>();
				cardGroup.add(card);
				cardGroup.add(card + 100);
				cardGroup.add(card + 100);
				this.push(cardGroup);
				this.stackHuxi.push(0);
				return true;
			}
		} else {
			if (CardUtil.cardNum(card - 100, this.cardList) >= 1 && CardUtil.cardNum(card, this.cardList) >= 2) {
				CardUtil.removeCard(this.cardList, card, 2);
				CardUtil.removeCard(this.cardList, card - 100, 1);
				List<Integer> cardGroup = new ArrayList<Integer>();
				cardGroup.add(card);
				cardGroup.add(card);
				cardGroup.add(card - 100);
				this.push(cardGroup);
				this.stackHuxi.push(0);
				return true;
			}
			if (CardUtil.cardNum(card - 100, this.cardList) >= 2) {
				CardUtil.removeCard(this.cardList, card, 1);
				CardUtil.removeCard(this.cardList, card - 100, 2);
				List<Integer> cardGroup = new ArrayList<Integer>();
				cardGroup.add(card);
				cardGroup.add(card - 100);
				cardGroup.add(card - 100);
				this.push(cardGroup);
				this.stackHuxi.push(0);
				return true;
			}
		}
		return false;
	}

	private boolean tryShunzi3(int card, EXPlayer player) {
		if (card % 100 == 2) {
			if (CardUtil.cardNum(card + 5, this.cardList) > 0 && CardUtil.cardNum(card + 8, this.cardList) > 0) {
				CardUtil.removeCard(this.cardList, card, 1);
				CardUtil.removeCard(this.cardList, card + 5, 1);
				CardUtil.removeCard(this.cardList, card + 8, 1);
				List<Integer> cardGroup = new ArrayList<Integer>();
				cardGroup.add(card);
				cardGroup.add(card + 5);
				cardGroup.add(card + 8);
				this.push(cardGroup);

				int huXi = Paixing.caclHuxi(RuleWeight.TYPE_CHOW, card);
				player.huXi += huXi;
				this.stackHuxi.push(huXi);
				return true;
			}
		}
		return false;
	}

	private boolean tryPair(int card) {
		if (this.pair_count > 0) {
			return false;
		}
		if (CardUtil.cardNum(card, this.cardList) >= 2) {
			CardUtil.removeCard(this.cardList, card, 2);
			List<Integer> cardGroup = new ArrayList<Integer>();
			cardGroup.add(card);
			cardGroup.add(card);
			this.push(cardGroup);
			this.pair_count = 1;
			this.stackHuxi.push(0);
			return true;
		}
		return false;
	}

	public boolean tryWin(EXPlayer player) {
		if (this.cardList.size() == 0) {
			if (player.tiCount + player.kongCount > 0) {
				if (this.pair_count == 1) {
					return true;
				}
				return false;
			} else {
				if (this.pair_count > 0) {
					return false;
				}
				return true;
			}
		}
		int activeCard = 0;
		for (int card : this.cardList) {
			if (card == 201 || card == 202) {
				activeCard = card;
				break;
			}
		}
		if (activeCard == 0) {
			activeCard = this.cardList.get(0);
		}
		if (activeCard % 100 == 1) {
			if (tryShunzi1(activeCard, player)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				int huXi = this.stackHuxi.pop();
				if (huXi > 0) {
					player.huXi -= huXi;
				}
			}
			if (tryKezi(activeCard, player)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				int huXi = this.stackHuxi.pop();
				if (huXi > 0) {
					player.huXi -= huXi;
				}
			}
			if (player.tiCount + player.kongCount > 0) {
				if (tryPair(activeCard)) {
					if (tryWin(player)) {
						return true;
					}
					this.pair_count = 0;
					this.rollBack();
					this.stackHuxi.pop();
				}
			}
			if (tryShunzi2(activeCard)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				this.stackHuxi.pop();
			}
		} else if (activeCard % 100 == 2) {
			if (tryShunzi3(activeCard, player)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				int huXi = this.stackHuxi.pop();
				if (huXi > 0) {
					player.huXi -= huXi;
				}
			}
			if (tryKezi(activeCard, player)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				int huXi = this.stackHuxi.pop();
				if (huXi > 0) {
					player.huXi -= huXi;
				}
			}
			if (player.tiCount + player.kongCount > 0) {
				if (tryPair(activeCard)) {
					if (tryWin(player)) {
						return true;
					}
					this.pair_count = 0;
					this.rollBack();
					this.stackHuxi.pop();
				}
			}
			if (tryShunzi1(activeCard, player)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				int huXi = this.stackHuxi.pop();
				if (huXi > 0) {
					player.huXi -= huXi;
				}
			}
			if (tryShunzi2(activeCard)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				this.stackHuxi.pop();
			}
		} else {
			if (tryKezi(activeCard, player)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				int huXi = this.stackHuxi.pop();
				if (huXi > 0) {
					player.huXi -= huXi;
				}
			}
			if (player.tiCount + player.kongCount > 0) {
				if (tryPair(activeCard)) {
					if (tryWin(player)) {
						return true;
					}
					this.pair_count = 0;
					this.rollBack();
					this.stackHuxi.pop();
				}
			}
			if (tryShunzi1(activeCard, player)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				int huXi = this.stackHuxi.pop();
				if (huXi > 0) {
					player.huXi -= huXi;
				}
			}
			if (tryShunzi2(activeCard)) {
				if (tryWin(player)) {
					return true;
				}
				this.rollBack();
				this.stackHuxi.pop();
			}
		}

		return false;
	}

	public WinCard(List<Integer> cardInhand, int addCard) {
		this.stack = new Stack<List<Integer>>();
		this.stackHuxi = new Stack<Integer>();
		this.cardList = new ArrayList<Integer>();
		this.cardList.addAll(cardInhand);
		if (addCard > 0) {
			this.cardList.add(addCard);
		}
		Collections.sort(this.cardList);
	}
}
