package extend.pk.player.state;

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

import com.game.Global;
import com.game.Router;
import com.game.data.Player;
import com.game.player.state.PlayerWaitState;
import com.game.state.StateBase;
import com.taurus.core.entity.ITArray;
import com.taurus.core.entity.ITObject;

import com.taurus.core.entity.TObject;
import extend.pk.CardGroup;
import extend.pk.CardObj;
import extend.pk.Config;
import extend.pk.EXActionEvent;
import extend.pk.EXMainServer;
import extend.pk.EXPlayer;
import extend.pk.EXRoom;
import extend.pk.RoomCard;
import extend.pk.room.state.EXRoomSetpState;
import extend.pk.uitl.CardCheck;
import extend.pk.uitl.CardConfig;
import extend.pk.uitl.CardUtil;

/**
 * 等待玩家出牌状态
 * 
 * 
 */
public class EXPlayerDiscardState extends StateBase<EXPlayer> {
	
	@Override
	public void enter(EXPlayer owner) {
		
		// 设置防作弊场开牌的标志
		owner.open = 1;

		EXRoom room = owner.getRoom();
		if (owner.cardInhand.size() == 0) {
			//如果最后一次打牌的座位等于自己  分数加到自己身上
			if(room.lastDiscardSeat == owner.seat) {
				//加5,10,k分
				room.add510kScore(owner);
				room.lastDiscardSeat = 0;
				//加5,10,k分
				int hasCardNum = 0;
				for (Map.Entry<Integer, Player> entry : room.playerMapBySeat.entrySet()) {
					EXPlayer player = (EXPlayer)entry.getValue();
					if (player.cardInhand.size() > 0)
					{
						hasCardNum++;
					}
				}
				if (hasCardNum <= 1)
				{
					this.over(owner);
					return;
				}
			}
			toNextState(owner);
			return;
		}

		//如果最后一次打牌的座位等于自己  分数加到自己身上
		if(room.lastDiscardSeat == owner.seat) {
			//加5,10,k分
			room.add510kScore(owner);
			//加5,10,k分
			int hasCardNum = 0;
			for (Map.Entry<Integer, Player> entry : room.playerMapBySeat.entrySet()) {
				EXPlayer player = (EXPlayer)entry.getValue();
				if (player.cardInhand.size() > 0)
				{
					hasCardNum++;
				}
			}
			if (hasCardNum <= 1)
			{
				this.over(owner);
				return;
			}
		}

		//如果最后一次的打牌的座位不等于零并且最后一次打牌的座位不等于自己
		if(room.lastDiscardSeat != 0 &&room.lastDiscardSeat != owner.seat) {
			
			boolean bNextBaodan = false;
			EXPlayer next = (EXPlayer) owner.room.playerMapBySeat.get(owner.nextSeat);
			if(next.cardInhand.size() == 1) {
				bNextBaodan = true;
			}
 			CardGroup big_ct = CardCheck.genOutCard(owner.cardInhand, room.discard,room.config,bNextBaodan);
			if(big_ct==null) {
				
				owner.stateMachine.changeState(Global.getState(EXPlayerPassState.class));
				return;
			}
			else {
			
				if(big_ct.config.type == Config.TYPE_ZHA ) {
					// 如果能出完，就自动出完
					if(big_ct.card_list.size() == owner.cardInhand.size()) {
						
						doAction(owner,big_ct,true);
						return;
					}
				}
				else {
					
					boolean bContainZha = false;
					
					boolean bThreeA = false;
					if(owner.room.config.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
						bThreeA = true;
					}
					
					Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(owner.cardInhand);
					for(Map.Entry<Integer, Integer> entry : cardMap.entrySet()) {
						
						int handNum = cardMap.get(entry.getKey());
	
						// 4张牌 不能出现在处大赞的牌型中
						if(handNum >= 4) {
							
							bContainZha = true;
						}
						
						// 三条A 不能拆
						if(entry.getKey() == RoomCard.CARD_A && bThreeA && handNum >= 3) {
							
							bContainZha = true;
						}
					}
					
					if(big_ct.card_list.size() == owner.cardInhand.size() && bContainZha == false) {
						doAction(owner,big_ct,true);
						return;
					}
				}
			}
		}
		else {
			
			// 自动出牌
			//CardGroup auto_ct = CardCheck.autoOutLastHand(owner.cardInhand, room.config,false);
			//if(auto_ct != null) {
			//	doAction(owner,auto_ct,true);
			//	return;
			//}
		}
		EXMainServer.gameCtr.discardTipEvent(owner);
		
		owner.startActionTimer();
	}

	@Override
	public void reload(EXPlayer owner) {
		EXMainServer.gameCtr.discardTipEvent(owner);
	}

	@Override
	public void exit(EXPlayer owner) {
		owner.stopActionTimer();
	}
	
	@Override
	public void toNextState(EXPlayer owner) {
		owner.stateMachine.changeState(Global.getState(PlayerWaitState.class));
		owner.room.stateMachine.changeState(Global.getState(EXRoomSetpState.class));
	}

	public void over(EXPlayer owner) {
		EXRoom room = owner.getRoom();
		if (room.winPlayerList.size() > 0)
		{
			EXPlayer win = room.winPlayerList.get(0);
			room.bankerSeat = win.seat;
			room.win = win;
		}
		else {
			if (room.playerMapByPlaying.size() == 2)
			{
				for (Map.Entry<Integer, Player> entry : room.playerMapByPlaying.entrySet()) {
					EXPlayer player = (EXPlayer) entry.getValue();
					if (player.cardInhand.size() == 0)
					{
						room.bankerSeat = player.seat;
						room.win = player;
						break;
					}
				}
			}
			else {
				for (Map.Entry<Integer, Player> entry : room.playerMapByPlaying.entrySet()) {
					EXPlayer player = (EXPlayer) entry.getValue();
					if (player.playerid != owner.playerid && player.cardInhand.size() == 0)
					{
						room.bankerSeat = player.seat;
						room.win = player;
					}
				}
			}
		}

		room.endGame();
	}

	@Override
	public void execute(EXPlayer owner, String cmd, int gid, Object param) {
		switch (cmd) {
		case EXActionEvent.EVENT_DISCARD:
			
			ITObject netParam = (ITObject) param;
			ITArray card_list = netParam.getTArray("card");
			ITArray all_card = netParam.getTArray("all_card");

			if (all_card != null)
			{
				ArrayList<Integer> temCardList = new ArrayList<Integer>();
				for(int i=0;i< all_card.size();++i) {
					temCardList.add(all_card.getInt(i));
				}
				Collections.sort(temCardList);

				ArrayList<Integer> temCardList2 = new ArrayList<Integer>();
				for(int i=0;i< owner.cardInhand.size();++i) {
					temCardList2.add(owner.cardInhand.get(i).card);
				}
				Collections.sort(temCardList2);

				if (!temCardList.equals(temCardList2))
				{
					ITObject reconParam = new TObject();
					owner.sendEvent(Router.GAME_EVT__UPDATE_RECONECT, reconParam);
					return;
				}
			}
			
			// 如果出的牌的个数为0 或者大于手牌的数目 则是非法的
			if (card_list.size() == 0 || card_list.size() > owner.cardInhand.size()) {
				EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_INVALID_TYPE);
				ITObject reconParam = new TObject();
				owner.sendEvent(Router.GAME_EVT__UPDATE_RECONECT, reconParam);
				return;
			}
			
			List<CardObj> list = CardUtil.toList(card_list);
			
			
			for(CardObj  card : list) {
				
				boolean bNotExisted = false;
				
				for(CardObj handc : owner.cardInhand) {
					if(card.card == handc.card) {
						bNotExisted = true;
						break;
					}
				}
				
				if(bNotExisted == false) {
					ITObject reconParam = new TObject();
					owner.sendEvent(Router.GAME_EVT__UPDATE_RECONECT, reconParam);
					return;
				}
			}
			
			if(owner.getRoom().firstCard != 0 && CardUtil.getCard1(owner.getRoom().firstCard, list) == null) {
				EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_MUST_OUT_MIN);
				return;
			}
			
			CardGroup ct = CardCheck.getType(list, owner.room.config);
			if(ct == null) {

				if (CardCheck.isConfig4_2_and_4_3(owner.room.config)) {
					//四带二/四带三摆尾
					if (list.size() == owner.cardInhand.size()) { //最后一把
						Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(list);

						if(owner.room.config.containsKey(Config.ROOM_CONFIG_SIDAI_2) && owner.room.config.getBoolean(Config.ROOM_CONFIG_SIDAI_2)) {
							if (list.size() == 5) {
								ct = CardCheck.checkSiWithTwo(cardMap,owner.room.config);
							}
						}

						if (ct == null) {
							if(owner.room.config.containsKey(Config.ROOM_CONFIG_SIDAI_3) && owner.room.config.getBoolean(Config.ROOM_CONFIG_SIDAI_3)) {
								if (list.size() == 5 || list.size() == 6) {
									ct = CardCheck.checkSiWithThree(cardMap,owner.room.config);
								}
							}
						}

						if (ct != null) {
							for(CardObj cardObj : owner.cardInhand) {
								ct.card_list.add(cardObj);
							}
							ct.card_list_mp = CardUtil.toTArray(ct.card_list);
						}
					}
				}


				if (ct == null) {
					EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_INVALID_TYPE);
					return;
				}
			}
			
			boolean bThreeA = false;
			if(owner.room.config.getInt(Config.ROOM_CONFIG_THREE_A) == 1) {
				bThreeA = true;
			}
			
			//验证客户端发过来的类型
			if(!CardCheck.tryType(ct,owner.cardInhand.size(),owner.room.config)) {
				
				// tryType 判断3条a判断不出来， 所以
				if(!(ct.config.type == Config.TYPE_ZHA && 
					card_list.size() == 3 &&
					bThreeA && 
					CardUtil.checkCard(RoomCard.CARD_A, list, 3))) {
					
					EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_INVALID_TYPE);
					return;
				}
			}
			
			// 如果炸弹不允许拆分，则检测非炸弹和4带三的牌型，看他们是否拆分了炸弹
			if(owner.room.config.getInt(Config.ROOM_CONFIG_DEMOLITION) == 1) {
				
				if(ct.config.type != Config.TYPE_ZHA ) {

					Map<Integer, Integer> hangCardMap =CardUtil.getCardNumMap(owner.cardInhand);
					Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(list);
					for(Map.Entry<Integer, Integer> entry : cardMap.entrySet()) {
						
						int handNum = hangCardMap.get(entry.getKey());
	
						// 4张牌 不能出现在处大赞的牌型中
						if(handNum >= 4) {
							
							EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_BOMB_CHAI);
							return;
						}
						
						// 三条A 不能拆
						if(entry.getKey() == RoomCard.CARD_A && bThreeA && handNum == 3) {
							
							EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_BOMB_CHAI);
							return;
						}
					}
				}
				else {
					Map<Integer, Integer> hangCardMap =CardUtil.getCardNumMap(owner.cardInhand);
					Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(list);
					for(Map.Entry<Integer, Integer> entry : cardMap.entrySet()) {

						int handNum = hangCardMap.get(entry.getKey());

						// 4张牌 不能出现在处大赞的牌型中
						if(handNum != ct.card_list.size()) {

							EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_BOMB_CHAI);
							return;
						}

						// 三条A 不能拆
						if(entry.getKey() == RoomCard.CARD_A && bThreeA && handNum == 3) {

							EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_BOMB_CHAI);
							return;
						}
					}
				}
			}
			
			doAction(owner,ct,false);
			break;
			
		case EXActionEvent.EVENT_PASS:
			
			if(owner.room.config.getInt(Config.ROOM_CONFIG_WILL_BE_OUT) == 1) {
				return;
			}
			pass(owner);
			
			break;
		case EXActionEvent.EVENT_OFFLINE:
			owner.startActionTimer();
			break;
		case EXActionEvent.EVENT_TIMER_AUTO:
		case EXActionEvent.EVENT_ENTRUST:
			
			AutoOut(owner);
			break;
		}
	}
	
	private void AutoOut(EXPlayer owner) {
		
		EXRoom room = owner.getRoom();
		
		if(room.lastDiscardSeat != 0 &&room.lastDiscardSeat != owner.seat) {
			
			CardGroup big_ct = null;
			EXPlayer playerNext = (EXPlayer)room.playerMapBySeat.get(owner.nextSeat);
			if(playerNext != null && room.discard.config.type ==Config.TYPE_DANPAI && playerNext.cardInhand.size() == 1) {
				
				Map<Integer, List<CardObj>> cardMap =CardUtil.getCardListMap(owner.cardInhand);
				big_ct = CardCheck.selectDanpai(cardMap,room.discard,room.config,true);
			}else {
				big_ct = CardCheck.tryBig(owner.cardInhand, room.discard);
			}

			if (big_ct != null) {
				big_ct.card_list_mp = CardUtil.toTArray(big_ct.card_list);
				doAction(owner,big_ct,true);
			} else {
				Global.logger.info("big_ct == null pass !!!!!!!!!!!!");
				pass(owner);
			}

		}else {
		
			// 在托管或者自动出牌的时候  系统先出炸弹，如果炸弹没有 再出单张
			// 将来可以把这个函数做的能智能一些，不光可以出炸弹 也可以出顺子飞机等等
			CardGroup out_ct = CardCheck.autoOut(owner.cardInhand, owner.room.config);
			if(out_ct == null) {
				
				out_ct = new CardGroup();
				List<CardObj> out_list = new ArrayList<>();
				out_ct.card_list = out_list;
				out_ct.config = CardConfig.DAN;
				out_ct.len = 1;
				
				if(room.firstCard != 0) {
					CardObj co = CardUtil.getCard1(room.firstCard, owner.cardInhand);
					out_list.add(co);
				}
				else
				{
					EXPlayer next = (EXPlayer) owner.room.playerMapBySeat.get(owner.nextSeat);
					if(next.cardInhand.size() == 1) {
						out_list.add(owner.cardInhand.get(owner.cardInhand.size() -1));
					}else {
						out_list.add(owner.cardInhand.get(0));
					}
				}
			}
			
			out_ct.card_list_mp = CardUtil.toTArray(out_ct.card_list);
			out_ct.min_card = out_ct.card_list.get(0).cardMod;
			
			doAction(owner,out_ct,true);
		}
	}

	private void pass(EXPlayer owner) {
		EXMainServer.gameCtr.pass(owner);//打不起过
		this.toNextState(owner);//下一位大哥
	}
    
	private void doAction(EXPlayer owner,CardGroup ct,boolean skip) {
		
		EXRoom room = owner.getRoom();
		boolean outcard = true;
		if(!skip) {
			
			if(room.lastDiscardSeat != 0 &&room.lastDiscardSeat != owner.seat) {
				outcard = CardCheck.tryCompete(room.discard, ct,room.config);
			}
			
			// 如果玩家的下家只有一张牌，玩家出单张必须是最大的
			if(outcard && ct.config.type == Config.TYPE_DANPAI) {
				/*
				EXPlayer playerNext = (EXPlayer)room.playerMapBySeat.get(owner.nextSeat);
				if(playerNext != null && playerNext.cardInhand.size() == 1) {
					
					Map<Integer, Integer> cardMap =CardUtil.getCardNumMap(owner.cardInhand);
					for(Integer number : cardMap.keySet()) {
						
						if(ct.min_card < number) {
							
							EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_MUST_OUT_MAX);
							return;
						}
					}
				}
				 */
			}
		}
		if(!outcard) {
			EXMainServer.gameCtr.sendPutError(owner,Config.PUT_ERROR_INVALID_TYPE);
			return;
		}

		/////////////////////////////////////////////
		for (Map.Entry<Integer, Player> entry : room.playerMapBySeat.entrySet()) {
			EXPlayer player = (EXPlayer)entry.getValue();

			ITObject param = new TObject();
			param.putInt("player", player.seat);
			param.putTArray("handCards", CardUtil.toTArray(player.cardInhand));
			player.sendEvent(Config.GAME_EVT_CARDINHAND, param);

			//Global.logger.info(player + " Config.GAME_EVT_CARDINHAND: " + param);
		}
		/////////////////////////////////////////////

		EXMainServer.gameCtr.outCard(owner,ct);

		if (owner.cardInhand.size() == 0)
		{
			room.winPlayerList.add(owner);
			int hasCardNum = 0;
			for (Map.Entry<Integer, Player> entry : room.playerMapBySeat.entrySet()) {
				EXPlayer player = (EXPlayer)entry.getValue();
				if (player.cardInhand.size() <= 0)
				{
					hasCardNum++;
				}
			}
			if (hasCardNum == 1)
			{
				ITObject param = new TObject();
				param.putInt("player", owner.seat);
				room.broadCastToClient(0, Config.GAME_EVT_SHANGYOU, param);
			}
		}

		this.toNextState(owner);


	}


}
