package extend.zp;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.game.GameController;
import com.game.Global;
import com.game.Util;
import com.game.data.Player;
import com.game.player.state.PlayerWaitState;
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 com.taurus.core.routes.ActionKey;
import com.taurus.core.util.Utils;
import com.taurus.permanent.data.Session;

import extend.zp.tip.Tip;
import extend.zp.tip.TipManager;
import extend.zp.uitl.CardUtil;
import extend.zp.uitl.TingCard;


/**
 * 
 * 
 */
public class EXGameController extends GameController {
	
	public EXGameController() {
		super();
	
	}
	

	@ActionKey(Config.GAME_ACTION)
	public void RouterAction(Session sender,ITObject params,int gid,Player owner) {
		if(Global.loggerDebug) {
			int id = params.getInt("id");
			if(id ==0) {
				Global.logger.info(owner + " pass!");
			}else {
				TipManager tipMgr =((EXPlayer)owner).tipMgr;
				if(tipMgr.tipMap.containsKey(id)) {
					Tip tip = tipMgr.tipMap.get(id);
					Global.logger.info(owner + " select_action type:"+tip.group_type+" card:"+tip.card);
				}
			}
		}
		
		owner.stateMachine.execute(EXActionEvent.EVENT_ACTION, 0, params);	
	}

	@ActionKey(Config.GAME_DIS_CARD)
	public void RouterDisCard(Session sender,ITObject params,int gid,Player owner) {
		owner.stateMachine.execute(EXActionEvent.EVENT_DISCARD, 0, params);	
	}
	

	@ActionKey(Config.GAME_PX_DATA)
	public void RouterPXData(Session sender,ITObject params,int gid,Player owner) {
		EXPlayer player = (EXPlayer) owner;
		player.pxData = params.getTArray("card_list");
		player.getRoom().changePaiXing(player.seat, params);
	}
	
	public void changeActiveSeat(EXRoom owner,int activeSeat) {
		owner.activeSeat = activeSeat;
		ITObject param = new TObject();
		param.putInt("seat", activeSeat);
		owner.broadCastToClient(0, Config.GAME_EVT_CHANGE_ACTIVE_PLAYER, param);
	}
		
	/*public void showCard(EXPlayer player,int card,boolean draw,int leftCount){
		ITObject param = new TObject();
		param.putInt( "card", card);
		param.putInt("seat", player.room.activeSeat);
		param.putBoolean("discard", !draw);
		param.putInt("left_count", leftCount);
		
		if(Global.loggerDebug) {
			Global.logger.info(player +" draw:"+ draw + " showcard["+card+"]");
		}
		player.room.broadCastToClient(0, Config.GAME_EVT_DRAW, param);
		
		player.getRoom().playBackData.showCardCommand(player.room.activeSeat, card,leftCount,!draw);
	}*/
	
	public void outCard(EXPlayer player,int discard){
		EXRoom room = player.getRoom();
		ITObject param = new TObject();
		param.putInt( "card", discard);
		param.putInt("seat", player.room.activeSeat);
		player.room.broadCastToClient(0, Config.GAME_EVT_DISCARD, param);
		CardUtil.removeCard(player.cardInhand, discard, 1);
		room.getPlayBack().addOutCardCommand(player.seat, discard);
		room.broadCastToServer(player.playerid, EXActionEvent.EVENT_OTHER_DISCARD, discard);
	}

	
	public void addCard(EXPlayer player,int card){
		ITObject param = new TObject();
		param.putInt( "card", card);
		param.putInt("seat", player.seat);
		if(Global.loggerDebug) {
			Global.logger.info(player + " addcard["+card+"]");
		}
		player.cardInhand.add(card);
		player.room.broadCastToClient(0, Config.GAME_EVT_ADDDRAW, param);
		player.getRoom().getPlayBack().addCardCommand(player.seat, card);
	}
	
	public void actionCard(EXPlayer player,int card,int type,int from_seat,ITArray opcard,int huxi, List<Integer> tyScore){
		ITObject paramBroadCast = new TObject();
		paramBroadCast.putInt("playerid", player.playerid);
		paramBroadCast.putInt("card", card);
		paramBroadCast.putInt("type", type);
		paramBroadCast.putInt("from_seat", from_seat);
		paramBroadCast.putInt("huxi", type == RuleWeight.TYPE_CHOW ? tyScore.get(0) : huxi);
		if(opcard!=null){
			paramBroadCast.putTArray("opcard", opcard);
		}
		EXRoom room = player.getRoom();
		if(Global.loggerDebug) {
			Global.logger.info(String.format("%s from_seat:%d card:%d type:%d", player,from_seat,card,type));
		}
		player.sendEvent(Config.GAME_EVT_ACTION, paramBroadCast);
		
		CardUtil.sendSuoCardEvent(player);
		
		
		room.getPlayBack().addActionCommand(player.seat, type, card, from_seat,opcard,huxi);
		ITObject param = new TObject();
		Utils.objectCopy(paramBroadCast, param);
		param.putInt("card", type == RuleWeight.TYPE_WEI ? 0 : card);
		param.putInt("huxi", type == RuleWeight.TYPE_WEI ? 0 : (type == RuleWeight.TYPE_CHOW ? tyScore.get(1) : huxi));
		room.broadCastToClient(player.playerid, Config.GAME_EVT_ACTION, param);
	}
	
	public void dealCard(EXRoom owner) {
		if(owner.maxPlayers == 2 && owner.config.containsKey(Config.ROOM_CONFIG_QUPAI) 
				&& owner.config.getBoolean(Config.ROOM_CONFIG_QUPAI)) {
			for(int num = 0; num < 19; num++) {
				owner.throwList.addInt(owner.card.pop());
			}
		}
		for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer)entry.getValue();
			player.cardInhand = owner.card.deal(19);
			/*if(player.seat == 1) {
				player.cardInhand = owner.card.dealFake1();
			} else if(player.seat == 2) {
				player.cardInhand = owner.card.dealFake2();
			} else if(player.seat == 3) {
				player.cardInhand = owner.card.dealFake3();
			}*/
			
			if(Global.loggerDebug) {
				Global.logger.info("roomId:" + owner.roomid + ",round:" + owner.round + ",player:" + player + ",cardInhand:" + player.cardInhand);
			}
		}
//		owner.card.cardList = owner.card.dealFake();
		if(Global.loggerDebug)
			Global.logger.info("roomId:" + owner.roomid + ",round:" + owner.round + ",cardList:" + owner.card.cardList);
		for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer)entry.getValue();
			ITObject param = new TObject();
			ITArray handCard = Util.toTArray(player.cardInhand);
			param.putTArray("card_list", handCard);
			param.putInt("bank_seat", player.room.bankerSeat);
			param.putInt("left_count", owner.card.getCount());
			param.putInt("round", owner.round);
			player.sendEvent(Config.GAME_EVT_PLAYER_DEAL, param);
			player.stateMachine.changeState(Global.getState(PlayerWaitState.class));
			if (player.seat != owner.bankerSeat) CardUtil.sendSuoCardEvent(player);
		}
	}
	
	public void getCard(EXPlayer player, int leftCount) {
		ITObject param = new TObject();
		param.putInt("card", player.getRoom().showCard);
		param.putInt("seat", player.room.activeSeat);
		param.putInt("left_count", leftCount);
		player.room.broadCastToClient(0, Config.GAME_EVT_DRAW, param);
		player.getRoom().getPlayBack().addGetCardCommand(player.room.activeSeat, player.getRoom().showCard, leftCount);
	}
	
	public void tipEvent(EXPlayer owner) {
		ITObject param = owner.tipMgr.toMP();
		owner.sendEvent(Config.GAME_EVT_FZTIPS, param);
	}
	
	public void discardTipEvent(EXPlayer owner) {
		owner.getRoom().currenDiscardSeat = owner.seat;
		ITObject param = new TObject();
		if (owner.tingMap.size() > 0) {
			ITArray infoList = new TArray();
			for (Entry<Integer, List<Integer>> entry : owner.tingMap.entrySet()) {
				ITObject obj = TObject.newInstance();
				obj.putInt("card", entry.getKey());
				obj.putTArray("ting_list", Util.toTArray(entry.getValue()));;
				infoList.addTObject(obj);
			}
			param.putTArray("ting", infoList);
		}
		owner.sendEvent(Config.GAME_EVT_DISCARD_TIP, param);
	}
	
	public void qiShouTing(EXPlayer owner) {
		owner.resetHuXi();
		List<OpCard> currentOpCardList = new ArrayList<OpCard>();
		List<Integer> cardList = new ArrayList<>(owner.cardInhand);
		List<Integer> myAngleCard = new ArrayList<>();
		myAngleCard.addAll(owner.cardInhand);
		Set<Integer> roomCardSet = new HashSet<>(); 
		for (int index = 1; index <= 10; index++) {
			roomCardSet.add(100 + index);
			roomCardSet.add(200 + index);
		}
		owner.tingList.clear();
		for (Integer tingCard : roomCardSet) {
			TingCard ting = new TingCard(cardList, tingCard, owner.AEhuXi, true, 
					currentOpCardList, owner.getRoom().config.getInt(Config.ROOM_CONFIG_WANFA));
			try {
				if (ting.checkHu()) {
					if (!Util.checkCard(tingCard, myAngleCard, 4)) {
						owner.tingList.add(tingCard);
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		owner.resetHuXi();
		if (owner.tingList.size() > 0) {
			ITObject param = new TObject();
			param.putTArray("tinglist", Util.toTArray(owner.tingList));
			owner.sendEvent(Config.GAME_EVT_TING, param);
		}
	}
	public void ting(EXPlayer owner) {
		owner.resetHuXi();
		List<OpCard> currentOpCardList = new ArrayList<OpCard>();
		Set<Integer> cardSet = new HashSet<>(owner.cardInhand);
		List<Integer> removeList = new ArrayList<>();
		List<Integer> myAngleCard = new ArrayList<>();
		myAngleCard.addAll(owner.cardInhand);
		for (Entry<Integer, Player> entry : owner.getRoom().playerMapBySeat.entrySet()) {
			EXPlayer player = (EXPlayer) entry.getValue();
			for (OpCard opCard : player.opCardList) {
				if ((opCard.type == RuleWeight.TYPE_WEI && owner.seat == entry.getKey()) || 
						!(opCard.type == RuleWeight.TYPE_WEI)) {
					myAngleCard.add(opCard.card1);
					myAngleCard.add(opCard.card2);
					myAngleCard.add(opCard.card3);
				}
			}
			myAngleCard.addAll(player.outcardList);
		}
		for (Integer card : cardSet) {
			if (Util.cardNum(card, owner.cardInhand) == 3 || owner.suoCardList.contains(card)) 
				removeList.add(card);
		}
		cardSet.removeAll(removeList);
		Set<Integer> roomCardSet = new HashSet<>(); 
		for (int index = 1; index <= 10; index++) {
			roomCardSet.add(100 + index);
			roomCardSet.add(200 + index);
		}
		Map<Integer, List<Integer>> tMap = new HashMap<Integer, List<Integer>>();
		for (Integer card : cardSet) {
			List<Integer> cardList = new ArrayList<>(owner.cardInhand);
			cardList.remove(card);
			for (Integer tingCard : roomCardSet) {
				currentOpCardList.clear();
				for (OpCard opCard : owner.opCardList) {
					currentOpCardList.add(new OpCard(opCard.type, opCard.card1, opCard.card2, opCard.card3, opCard.huXi));
				}
				TingCard ting = new TingCard(cardList, tingCard, owner.AEhuXi, true, 
						currentOpCardList, owner.getRoom().config.getInt(Config.ROOM_CONFIG_WANFA));
				try {
					if (ting.checkHu()) {
						if (!Util.checkCard(tingCard, myAngleCard, 4)) {
							if (tMap.containsKey(card)) {
								tMap.get(card).add(tingCard);
							}else {
								List<Integer> list = new ArrayList<>();
								list.add(tingCard);
								tMap.put(card, list);
							}
						}
					}
				} catch (Exception e) {
					e.printStackTrace();
				}
			}
		}
		owner.resetHuXi();
		if (tMap.size() > 0) {
			owner.tingMap.clear();
			owner.tingMap.putAll(tMap);
		}
	}
	
	public void winEvent(EXPlayer owner,int from_seat) {
		ITArray cardInHand = TArray.newInstance();
		for (int card1 : owner.cardInhand) {
			cardInHand.addInt(card1);
		}
		ITObject param = new TObject();
		param.putTArray("card", cardInHand);
		param.putInt("seat", owner.seat);
		param.putInt("from_seat", from_seat);
		param.putInt("win_card", owner.winCard);
		param.putInt("hutype", owner.hutype);
		
		EXRoom room = owner.getRoom();
		room.broadCastToClient(0, Config.GAME_EVT_HU, param);
		room.getPlayBack().addWinCardCommand(owner.seat, false);
	}
	
	private ITObject getRoomResultData(EXRoom owner) {
		ITObject mp = TObject.newInstance();
		mp.putBoolean("liuju", owner.liuju);

		mp.putInt("active_player", owner.playerMapBySeat.get(owner.activeSeat).playerid);
		long time = System.currentTimeMillis();
		long t = time / 1000;
		mp.putLong("time", t);
		mp.putTArray("left_cards", Util.toTArray(owner.card.cardList));
		if(owner.maxPlayers == 2) {
			mp.putTArray("throw_list", owner.throwList);
		}
		if (owner.config.containsKey(Config.ROOM_CONFIG_ZHUANGXIAN)) {
			mp.putInt("score_pool", owner.douLiuZi);
		}
		ITArray infoList = new TArray();
		for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer) entry.getValue();
			ITObject param = new TObject();
			param.putInt("seat", player.seat);
			param.putInt("win_card", player.winCard);
			param.putBoolean("is_win", player.winer == 1);
			param.putInt("hu_xi", player.allHuXi);
			param.putInt("ying_xi", player.huXi);
			param.putInt("round_score", player.score.round_score);
			param.putInt("total_score", player.score.total_score);
			if (owner.config.containsKey(Config.ROOM_CONFIG_ZHUANGXIAN)) {
				param.putInt("douliszi_score", player.score.round_log.get(EXScore.DOULIUZISCORE) == null ? 0 :
					player.score.round_log.get(EXScore.DOULIUZISCORE));
			}
			ITArray mtList = TArray.newInstance();
			for (MingTang mingTang : player.winMtList) {
				ITObject obj = TObject.newInstance();
				obj.putInt("mingtang", mingTang.type);
				obj.putInt("type", mingTang.v_type);
				obj.putInt("score", mingTang.value);

				mtList.addTObject(obj);
			}
			param.putTArray("mt_list", mtList);
			if (player.winer == 1) {
				ITArray cardList = TArray.newInstance();
				for (OpCard opCard : player.handCard) {
					ITObject obj = TObject.newInstance();
					obj.putInt("type", opCard.type);
					obj.putInt("huxi", opCard.huXi);
					ITArray op = TArray.newInstance();
					if(opCard.card1 > 0) op.addInt(opCard.card1);
					if(opCard.card2 > 0) op.addInt(opCard.card2);
					if(opCard.card3 > 0) op.addInt(opCard.card3);
					obj.putTArray("opcard", op);
					cardList.addTObject(obj);
				}
				for (OpCard opCard : player.currentOpCardList) {
					ITObject obj = TObject.newInstance();
					obj.putInt("type", opCard.type);
					obj.putInt("huxi", opCard.huXi);
					ITArray op = TArray.newInstance();
					if(opCard.card1 > 0) op.addInt(opCard.card1);
					if(opCard.card2 > 0) op.addInt(opCard.card2);
					if(opCard.card3 > 0) op.addInt(opCard.card3);
					obj.putTArray("opcard", op);
					cardList.addTObject(obj);
				}
				param.putTArray("win_card_list", cardList);
			} else {
				ITArray handCard = Util.toTArray(player.cardInhand);
				param.putTArray("hand_card", handCard);
				ITArray opCardList = TArray.newInstance();
				for (OpCard opCard : player.opCardList) {
					ITObject obj = TObject.newInstance();
					obj.putInt("type", opCard.type);
					obj.putInt("huxi", opCard.huXi);
					obj.putInt("card", opCard.card1);
					ITArray op = TArray.newInstance();
					op.addInt(opCard.card2);
					if(opCard.card3 > 0) op.addInt(opCard.card3);
					obj.putTArray("opcard", op);
					opCardList.addTObject(obj);
				}
				param.putTArray("opcard_list", opCardList);
			}
			player.hp_info(param);
			infoList.addTObject(param);
		}
		mp.putTArray("info_list", infoList);
		return mp;
	}
	

	public void roomResult(EXRoom owner) {
		ITObject mp = TObject.newInstance();
		mp.putInt("type", 0);
		ITObject result = getRoomResultData(owner);
		owner.getPlayBack().addResultCommand(result);
		mp.putTObject("result", result);
		owner.broadCastToClient(0, Config.GAME_EVT_RESULT1, mp);
	}
	

	public void roomTotalResult(EXRoom owner,boolean dissmiss) {
		ITObject data = TObject.newInstance();
		long t = System.currentTimeMillis() / 1000;
		data.putLong("time", t);
		ITArray infoList = new TArray();
		int douLiuZiScore = 0;
		if (owner.douLiuZi > 0) {
			douLiuZiScore = owner.douLiuZi / owner.maxPlayers;
		}
		for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer) entry.getValue();
			if (owner.douLiuZi > 0) {
				owner.addDouLiuZiScore(player,player.seat == 1 ? -douLiuZiScore -
						(owner.douLiuZi - douLiuZiScore*owner.maxPlayers) : -douLiuZiScore, EXScore.DOULIUZISCORE);
			}
			ITObject param = new TObject();
			param.putInt("seat", player.seat);
			param.putTObject("settle_log", player.settleLog.toTObject());
			param.putInt("total_score", player.score.total_score);
			player.hp_info(param);
			infoList.addTObject(param);
		}
		data.putTArray("info_list", infoList);
		
		ITObject mp = TObject.newInstance();
		mp.putInt("type", dissmiss?2:1);
		if(!dissmiss) {
			ITObject result = getRoomResultData(owner);
			owner.getPlayBack().addResultCommand(result);
			mp.putTObject("result", result);
		}
		mp.putTObject("total_result", data);
		
		owner.broadCastToClient(0, Config.GAME_EVT_RESULT1, mp);
		
	}
}
