package extend.zp;

import java.util.*;
import java.util.Map.Entry;

import com.game.Global;
import com.game.Util;
import com.game.data.Player;
import com.game.data.Room;
import com.game.data.Score;
import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TArray;
import com.taurus.core.entity.TObject;

import extend.zp.player.rule.RuleChi;
import extend.zp.tip.IRuleBase;
import extend.zp.tip.Tip;
import extend.zp.tip.TipManager;
import extend.zp.uitl.CardUtil;
import extend.zp.uitl.ChowCard;
import extend.zp.uitl.Paixing;

/**
 * 
 * 
 *
 *         2017��8��30�� EXPlayer.java
 */
public class EXPlayer extends Player {
	// ����
	public List<Integer>	cardInhand;
	// ������
	public List<Integer>	outcardList;
	// ������
	public List<Integer>	outcardExList;

	public ITArray			opCard;

	public int				biCard;

	public List<int[]>		tiGroup;
	public List<int[]>		liuGroup;
	public List<int[]>		paoGroup;
	public List<int[]>		kanGroup;
	public List<int[]>		pongGroup;
	public List<int[]>		weiGroup;
	public List<int[]>		chowGroup;
	public List<OpCard>		opCardList;

	public Stack<OpCard>	handCard;
	public List<Integer>	handCardEx;

	public HashSet<Integer>	chouChiSet;
	public HashSet<Integer>	chouChiExSet;
	public HashMap<Integer, Integer> chouChiTypeMap;
	public HashSet<Integer>	chouPongSet;
	public HashSet<Integer>	notPutSet;
	public HashSet<Integer> notChiSet;

	public HashSet<Integer> guoChiSet;



	public HashMap<Integer, Integer> notChiTypeMap;



	public int				drawCard	= 0;
	public int				winCard		= 0;
	public int				winScore	= 0;
	public int				winFan		= 0;
	public List<MingTang>	mingtangList;

	public int				kongCount	= 0;
	public int				tiCount		= 0;
	// ��Ϣ
	public int				huXi		= 0;
	
	public int				total_huxi	= 0;
	
	public boolean			isTingHu	= true;

	// �Ƿ�����ү
	public boolean			isLaoYe		= false;

	public boolean			isMingTang	= true;

	public TipManager		tipMgr;
	
	public Tip				actionTip;

	public int piao = -1;

	public boolean					isDiHu		= true;
	public boolean                  isGuoliu    = false;

	public boolean					isDeadPut = false;

	public EXPlayer(int playerid, Room table, String session_id) {
		super(playerid, table, session_id);

		cardInhand = new ArrayList<>();
		outcardList = new ArrayList<>();
		outcardExList = new ArrayList<>();

		tiGroup = new ArrayList<>();
		liuGroup = new ArrayList<>();
		paoGroup = new ArrayList<>();
		kanGroup = new ArrayList<>();
		pongGroup = new ArrayList<>();
		weiGroup = new ArrayList<>();
		chowGroup = new ArrayList<>();
		opCardList = new ArrayList<>();
		mingtangList = new ArrayList<>();

		opCard = new TArray();
		chouChiSet = new HashSet<>();
		chouChiTypeMap = new HashMap<>();
		chouChiExSet = new HashSet<>();
		chouPongSet = new HashSet<>();
		notPutSet = new HashSet<>();
		notChiSet = new HashSet<>();
		guoChiSet = new HashSet<>();
		notChiTypeMap = new HashMap<>();

		handCard = new Stack<OpCard>();
		handCardEx = new ArrayList<>();

		tipMgr = new TipManager(this);

		isDiHu = true;

		isGuoliu = false; //过溜

		isDeadPut = false;
	}

	protected Score newScore() {
		return new EXScore(this);
	}

	public void initOpCard(ITArray opcard) {
		this.opCard.clear();
		for (int i = 0; i < opcard.size(); ++i) {
			this.opCard.addInt(opcard.getInt(i));
		}
	}

	public ITObject getReloadInfo(boolean self) {
		ITObject playerData = super.getReloadInfo();
		ITArray disCard = Util.toTArray(this.outcardList);
		playerData.putTArray("outcard_list", disCard);
		playerData.putInt("score", this.score.total_score);
		playerData.putInt("hu_xi", this.getShowHuXi(self));
		playerData.putInt("piao", this.piao);
		int size = 0;
		ITArray opcards = TArray.newInstance();
		for (OpCard opcard : opCardList) {
			if (opcard.type == RuleWeight.TYPE_TI && opcard.pailie == true)
			{
			    size += 4;
			    continue;
			}
			if (opcard.type == RuleWeight.TYPE_KAN && opcard.pailie == true)
			{
				size += 3;
				continue;
			}
			ITObject opcardParam = new TObject();
			opcardParam.putInt("type", opcard.type);
			opcardParam.putInt("card1", opcard.card1);
			opcardParam.putInt("card2", opcard.card2);
			opcardParam.putInt("card3", opcard.card3);
			opcards.addTObject(opcardParam);
		}
		playerData.putInt("card_count", this.cardInhand.size() + size);
		playerData.putTArray("opcard", opcards);
		return playerData;
	}

	public int getShowHuXi(boolean self) {
		int huXi = 0;
		for (OpCard opCard : this.opCardList) {
			if (opCard.type == RuleWeight.TYPE_KAN || opCard.type == RuleWeight.TYPE_TI && opCard.pailie == true) {
				continue;
			}
			huXi += opCard.huXi;
		}
		return huXi;
	}

	public void resetHuXi() {
		this.huXi = 1; //胡算一分
		for (OpCard opCard : this.opCardList) {
			this.huXi += opCard.huXi;
		}
		if (tiGroup.size() > 0)
		{
			this.huXi -= Paixing.caclHuxi(RuleWeight.TYPE_TI, 0) * tiGroup.size();
		}
	}

	public void clear() {
		this.isDiHu = true;
		this.cardInhand.clear();
		this.winer = 0;
		this.outcardList.clear();
		this.outcardExList.clear();
		this.drawCard = 0;
		this.winScore = 0;
		this.winFan = 0;
		this.kongCount = 0;
		this.tiCount = 0;
		this.huXi = 0;
		this.isTingHu = true;
		this.isLaoYe = false;
		this.isMingTang = true;
		this.tiGroup.clear();
		this.liuGroup.clear();
		this.paoGroup.clear();
		this.kanGroup.clear();
		this.pongGroup.clear();
		this.weiGroup.clear();
		this.chowGroup.clear();
		this.opCardList.clear();
		this.chouChiSet.clear();
		this.chouChiExSet.clear();
		this.chouChiTypeMap.clear();
        this.notChiTypeMap.clear();
		this.chouPongSet.clear();
		this.notPutSet.clear();
		this.mingtangList.clear();
		this.score.resetRound();
		this.piao = -1;
		this.isDeadPut = false;
	}

	public EXRoom getRoom() {
		return (EXRoom) room;
	}
	/**
	 * �Զ����ƣ��йܣ�
	 */
	public  Integer autoDiscard(){
		Map<Integer, Integer> cardNum=CardUtil.getCardNumMap(this.cardInhand);
		for (Entry<Integer, Integer> card : cardNum.entrySet()) {
			 if (card.getValue()==1||card.getValue()==2) {
			 	if (!this.notPutSet.contains(card.getKey()))
				{
					return card.getKey();
				}
			}
		}
		return 0;
	}

	public void handleDeadPut()
	{
		ArrayList<Integer> tempList = new ArrayList<>();
		tempList.addAll(this.cardInhand);
		for (int i = 0; i < kanGroup.size(); i++) {
			tempList.add(kanGroup.get(i)[0]);
			tempList.add(kanGroup.get(i)[0]);
			tempList.add(kanGroup.get(i)[0]);
		}

		for (int i = 0; i < tiGroup.size(); i++) {
			tempList.add(tiGroup.get(i)[0]);
			tempList.add(tiGroup.get(i)[0]);
			tempList.add(tiGroup.get(i)[0]);
			tempList.add(tiGroup.get(i)[0]);
		}

		for(int i = 0; i < tempList.size(); i++) {
			int card = tempList.get(i);
			if (!notPutSet.contains(card))
			{
				return;
			}
		}

		isDeadPut = true;
	}
	public boolean chi(int eventCard, IRuleBase rule) {
		EXPlayer activePlayer = (EXPlayer) this.room.playerMapBySeat.get(this.room.activeSeat);
		ArrayList<Integer> tempList = new ArrayList<>();
		tempList.addAll(this.cardInhand);
		for (int i = 0; i < kanGroup.size(); i++) {
			tempList.add(kanGroup.get(i)[0]);
			tempList.add(kanGroup.get(i)[0]);
			tempList.add(kanGroup.get(i)[0]);
		}
		for (int i = 0; i < tiGroup.size(); i++) {
			tempList.add(tiGroup.get(i)[0]);
			tempList.add(tiGroup.get(i)[0]);
			tempList.add(tiGroup.get(i)[0]);
			tempList.add(tiGroup.get(i)[0]);
		}

		if (tempList.size() <= 2) {
			return false;
		}
		if (eventCard == 0) {
			return false;
		}
		if (this.isEntrust()) {
			this.chouChiSet.add(eventCard);
			return false;
		}

		Global.logger.info("user: "+ this.playerid+" chi==========>  chouChiSet = "+chouChiSet+ "  eventCard ="+eventCard);
		// ����
		if (this.chouChiSet.contains(eventCard)) {
			if (this.chouChiTypeMap.containsKey(eventCard)) {
				//可以吃2 7 10
				Global.logger.info("user: "+ this.playerid + " maybe can chi for 2 7 10 " + " for eventCard:"+eventCard);
				//return false;
			} else {
				Global.logger.info("user: "+ this.playerid+"  chouChiSet = "+chouChiSet + "  ==> false for eventCard:"+eventCard);
				return false;
			}
		}

		HashSet<Integer> getChi = new HashSet<>();
		getChi.addAll(this.guoChiSet);
		Global.logger.info("jefe getChi : "+ this.playerid+" chi==========> = "+getChi+ "  eventCard ="+eventCard);

		// ����
		if (this.chouChiExSet.contains(eventCard) && this.getRoom().throwCardsSet.contains(eventCard)) {
			return false;
		}

		if (CardUtil.cardNum(eventCard, this.outcardExList) != 0) {
			return false;
		}
		if (activePlayer.nextSeat != this.seat && activePlayer.seat != this.seat) {
			return false;
		}
		//if (this.getRoom().checkPao(eventCard, rule  instanceof RuleChi)) {
		//	return false;
		//}

		ChowCard chow = new ChowCard(tempList, eventCard);
		ITArray list = TArray.newInstance();
		boolean isChi = chow.tryChow(list);
		if (isChi) {
			boolean hasChi = false;

			int weight = activePlayer.seat != this.seat ? RuleWeight.CHOW1 : RuleWeight.CHOW2;
			for (int i = 0; i < list.size(); ++i) {
				ITObject obj = list.getTObject(i);
				ITArray opCard = obj.getTArray("opcard");
				int chowcard1 = opCard.getInt(0);
				int chowcard2 = opCard.getInt(1);

				if (this.chouChiTypeMap.containsKey(eventCard)) {
					//Global.logger.info("====> opCard : "+opCard);
					if (isThreeCard2_7_10(chowcard1, chowcard2, eventCard)) {
						//可以吃2 7 10
						Global.logger.info("user: "+ this.playerid + " can chi for 2 7 10 " + " for eventCard:"+eventCard);
						continue;
					} else {
						Global.logger.info("user dd: "+ this.playerid + " can't chi for 2 7 10 " + " for eventCard:"+eventCard);
						//判断卡隆
						if(!getChi.contains(eventCard)){
							//处理卡隆
							//Global.logger.info("jefe step1"+eventCard);
							//处理最大最小
							if (this.chouChiTypeMap.containsKey(eventCard-3)){
								//Global.logger.info("jefe step2"+eventCard);
								//eventcard 最大
								if (eventCard<chowcard1&&eventCard<chowcard2){
									Global.logger.info("user max: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
								}else{
									if (chowcard2>chowcard1){
										//大于
										if (eventCard-chowcard1==1&&chowcard2-eventCard==1){
											Global.logger.info("user ka1long: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
										}else{
											continue;//都不能吃
										}
									}else{
										//小于
										if (chowcard1-eventCard==1&&eventCard-chowcard2==1){
											Global.logger.info("user ka3long: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
										}else{
											continue;//都不能吃
										}
									}
								}
							}else if (this.chouChiTypeMap.containsKey(eventCard+3)){
								//Global.logger.info("jefe step3"+eventCard);
								if (eventCard>chowcard1&&eventCard>chowcard2){
									Global.logger.info("user min: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
								}else{
									if (chowcard2>chowcard1){
										//大于
										if (eventCard-chowcard1==1&&chowcard2-eventCard==1){
											Global.logger.info("user ka1long: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
										}else{
											continue;//都不能吃
										}
									}else{
										//小于
										if (chowcard1-eventCard==1&&eventCard-chowcard2==1){
											Global.logger.info("user ka3long: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
										}else{
											continue;//都不能吃
										}
									}
								}
							}else{
								//Global.logger.info("jefe step4"+eventCard);
								if (chowcard2>chowcard1){
									//大于
									if (eventCard-chowcard1==1&&chowcard2-eventCard==1){
										Global.logger.info("user kalong: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
									}else{
										continue;//都不能吃
									}
								}else{
									//小于
									if (chowcard1-eventCard==1&&eventCard-chowcard2==1){
										Global.logger.info("user ka2long: "+ this.playerid + "chowcard1:"+chowcard1+" chowcard2: "+chowcard2+" eventCard :"+eventCard);
										Tip tip = new Tip(eventCard, opCard, weight, rule, RuleWeight.TYPE_CHOW);
										tip.bi_list = obj.getTArray("bi_list");
										this.tipMgr.addTip(tip);
									}else{
										continue;//都不能吃
									}
								}
							}

						}else{
							Global.logger.info("jefe step5"+eventCard);
							continue;//都不能吃
						}

					}
				}

				hasChi = true;

				Tip tip = new Tip(eventCard, opCard, weight, rule, RuleWeight.TYPE_CHOW);
				tip.bi_list = obj.getTArray("bi_list");
				this.tipMgr.addTip(tip);

				//__notChi(this,  chowcard1, chowcard2, eventCard);
				__notChi1(this,  chowcard1, chowcard2, eventCard);

				HashSet<Integer> notChiSet11 = this.notChiSet;
				Global.logger.info("---> user: "+ this.playerid+" opCard = "+opCard+" notChiSet = "+notChiSet);
				Global.logger.info("---> user: "+ this.playerid+" chouChiSet = "+this.chouChiSet);
			}

			return hasChi;
		} else {
			this.chouChiExSet.add(eventCard);
		}
		return isChi;
	}

	private static boolean isThreeCard2_7_10(int card1, int card2, int card3) {
		int mod1 = card1%100;
		int mod2 = card2%100;
		int mod3 = card3%100;

		HashSet<Integer> set = new HashSet<>();
		set.add(mod1);
		set.add(mod2);
		set.add(mod3);

		if ((mod1 + mod2 + mod3 == 2 + 7 + 10) && set.contains(2) && set.contains(7) && set.contains(10)) {
			return true;
		} else {
			return false;
		}
	}


	private static final void __notChi(EXPlayer player, int chowcard1, int chowcard2, int card) {
		player.notChiSet.add(card);
		Global.logger.info("---> notchi jefe: chowcard1:"+ chowcard1+" chowcard2: "+chowcard2+"card:"+card);
		if (chowcard1 - chowcard2 == 1) {
			if (chowcard2 % 100 == 1) {
				player.notChiSet.add(chowcard2 + 2);
			} else if (chowcard2 % 100 == 9) {
				player.notChiSet.add(chowcard2 - 1);
			} else {
				player.notChiSet.add(chowcard2 - 1);
				player.notChiSet.add(chowcard2 + 2);
			}
		} else if (chowcard1 - chowcard2 == 2) {
			player.notChiSet.add(chowcard2 + 1);
		} else if (chowcard2 - chowcard1 == 1) {
			if (chowcard1 % 100 == 1) {
				player.notChiSet.add(chowcard1 + 2);
			} else if (chowcard1 % 100 == 9) {
				player.notChiSet.add(chowcard1 - 1);
			} else {
				player.notChiSet.add(chowcard1 - 1);
				player.notChiSet.add(chowcard1 + 2);
			}
		} else if (chowcard2 - chowcard1 == 2) {
			player.notChiSet.add(chowcard1 + 1);
		}
	}

	private static final void __notChi1(EXPlayer player, int chowcard1, int chowcard2, int card) {
		player.notChiSet.add(card);
		player.guoChiSet.add(card);
		//player.notChiTypeMap.put(card, 0);
		Global.logger.info("---> notchi jefe: chowcard1:"+ chowcard1+" chowcard2: "+chowcard2+"card:"+card);
		if (chowcard1 - chowcard2 == 1) {
			if (chowcard2 % 100 == 1) {
				player.notChiSet.add(chowcard2 + 2);
				player.notChiTypeMap.put(chowcard2 + 2, 0);
			} else if (chowcard2 % 100 == 9) {
				player.notChiSet.add(chowcard2 - 1);
				player.notChiTypeMap.put(chowcard2 - 1, 0);
			} else {
				player.notChiSet.add(chowcard2 - 1);
				player.notChiSet.add(chowcard2 + 2);
				player.notChiTypeMap.put(chowcard2 - 1, 0);
				player.notChiTypeMap.put(chowcard2 + 2, 0);
			}
		} else if (chowcard1 - chowcard2 == 2) {
			player.notChiSet.add(chowcard2 + 1);
			player.notChiTypeMap.put(chowcard2 + 1, 0);
		} else if (chowcard2 - chowcard1 == 1) {
			if (chowcard1 % 100 == 1) {
				player.notChiSet.add(chowcard1 + 2);
				player.notChiTypeMap.put(chowcard1 + 2, 0);
			} else if (chowcard1 % 100 == 9) {
				player.notChiSet.add(chowcard1 - 1);
				player.notChiTypeMap.put(chowcard1 - 1, 0);
			} else {
				player.notChiSet.add(chowcard1 - 1);
				player.notChiSet.add(chowcard1 + 2);
				player.notChiTypeMap.put(chowcard1 - 1, 0);
				player.notChiTypeMap.put(chowcard1 + 2, 0);
			}
		} else if (chowcard2 - chowcard1 == 2) {
			player.notChiSet.add(chowcard1 + 1);
			player.notChiTypeMap.put(chowcard1 + 1, 0);
		} else { //2 7 10
			/*if (isThreeCard2_7_10(chowcard1,chowcard2,card)){
				player.notChiSet.add(chowcard1);
				player.notChiSet.add(chowcard2);
				player.notChiTypeMap.put(chowcard1, 0);
				player.notChiTypeMap.put(chowcard2, 0);
				player.notChiTypeMap.put(card, 0);
			}*/
			//player.notChiSet.add(card);
			//player.notChiTypeMap.put(card, 0);
		}

	}

}
