package extend.mj;

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.permanent.data.Session;
import extend.mj.tip.Tip;
import extend.mj.tip.TipManager;
import extend.mj.uitl.CardUtil;
import extend.mj.uitl.WinCard;

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

/**
 * 
 * 
 *
 * EXGameController.java
 */
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.weight+" 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_PIAO)
	public void RouterPiao(Session sender,ITObject params,int gid,Player owner) {
		owner.stateMachine.execute(EXActionEvent.EVENT_PIAO, 0, params);
	}

	public void changeActiveSeat(EXRoom owner,int activeSeat) {
		owner.activeSeat = activeSeat;
		TObject param = new TObject();
		param.putInt("seat", activeSeat);
		owner.broadCastToClient(0, Config.GAME_EVT_CHANGE_ACTIVE_PLAYER, param);
	}
		
	public void getCard(EXPlayer player,int leftCount){
		ITObject otherParam = new TObject();
		otherParam.putInt("card", 0);
		otherParam.putInt("seat", player.room.activeSeat);
		otherParam.putInt("left_count", leftCount);
		
		ITObject param = new TObject();
		param.putInt( "card", player.drawCard );
		param.putInt("seat", player.room.activeSeat);
		param.putInt("left_count", leftCount);
		player.cardInhand.add(player.drawCard);
		param.putTArray("card_list", Util.toTArray(player.cardInhand));
		param.putTArray("outcard_list", Util.toTArray(player.outcardList));
		long start_time = System.currentTimeMillis();
		param.putTArray("ting_list", getTingList(player));
		long use_time = System.currentTimeMillis() - start_time;
		Global.logger.info("---------------getTingList use time:" + use_time);
		player.sendEvent(Config.GAME_EVT_DRAW, param);
		if(Global.loggerDebug) {
			Global.logger.info(player + " drawcard["+player.drawCard+"]");
		}
		player.room.broadCastToClient(player.playerid, Config.GAME_EVT_DRAW, otherParam);
		((EXPlayBack)player.getRoom().playBackData).addGetCardCommand(player.room.activeSeat, player.drawCard,leftCount);
	}

	public void outCard(EXPlayer player,int discard){
		ITObject response = new TObject();
		response.putInt("seat", player.seat);
		response.putInt("card", discard);
		player.room.broadCastToClient(0, Config.GAME_EVT_DISCARD, response);
		EXRoom room = player.getRoom();
		((EXPlayBack)room.playBackData).addOutCardCommand(player.seat, discard);
		
		room.activeCard = discard;
		room.lastDiscardSeat = player.seat;
		room.currenDiscardSeat = 0;
		if (room.isGengZhuang)
		{
			if (room.bankerSeat == player.seat && player.opCardList.size() == 0 && player.outcardList.size() == 0)
			{
				if (room.gent_zhuan_nextSeat == 0 && room.first_zhuang_card == 0)
				{
					room.first_zhuang_card = discard;
					room.geng_zhuan_num = 1;
					room.gent_zhuan_nextSeat = player.nextSeat;
				}
				else
				{
					room.isGengZhuang = false;
				}
			}
			else if (room.gent_zhuan_nextSeat == player.seat && player.opCardList.size() == 0 && player.outcardList.size() == 0 && room.first_zhuang_card == discard)
			{
				room.geng_zhuan_num += 1;
				room.gent_zhuan_nextSeat = player.nextSeat;
				if (room.geng_zhuan_num >= room.maxPlayers)
				{
					if (room.config.getBoolean(Config.ROOM_CONFIG_GENGZHUAN))
					{
						EXPlayer bankerPlayer =  (EXPlayer)room.playerMapBySeat.get(room.bankerSeat);
						for (Entry<Integer, Player> entry : room.playerMapById.entrySet()) {
							EXPlayer otherPlayer = (EXPlayer) entry.getValue();
							if (otherPlayer.playerid != bankerPlayer.playerid)
							{
								room.addScore(otherPlayer,bankerPlayer, 1, EXScore.GENG_ZHUAN);
							}
						}
					}
					room.isGengZhuang = false;
				}
			}
			else
			{
				room.isGengZhuang = false;
			}
		}

		player.outcardList.add(discard);
		Util.removeCard(player.cardInhand, discard, 1);
		if(Global.loggerDebug) {
			Global.logger.info(player + " outcard["+discard+"]");
		}
		room.broadCastToServer(player.playerid, EXActionEvent.EVENT_OTHER_DISCARD, discard);
	}
	
	

	public void actionCard(EXPlayer player,int card,int type,int from_seat,ITArray opcardArray){
		EXRoom room = player.getRoom();
		ITObject paramBroadCast = new TObject();
		paramBroadCast.putInt("playerid", player.playerid);
		paramBroadCast.putInt("card", card);
		paramBroadCast.putInt("type", type);
		paramBroadCast.putInt("from_seat", from_seat);
		if(opcardArray!=null){
			paramBroadCast.putTArray("opcard", opcardArray);
		}
		ITArray result = new TArray();
		for (Entry<Integer, Player> entry : room.playerMapById.entrySet()) {
			EXPlayer __player = (EXPlayer) entry.getValue();
			ITObject __info = new TObject();
			__info.putInt("playerid", __player.playerid);
			__info.putTArray("outcard_list", Util.toTArray(__player.outcardList));
			result.addTObject(__info);
		}
		paramBroadCast.putTArray("outcard_list", result);

		if(Global.loggerDebug) {
			Global.logger.info(String.format("%s from_seat:%d card:%d type:%d ", player,from_seat,card,type));
		}
		room.broadCastToClient(player.playerid, Config.GAME_EVT_ACTION, paramBroadCast);

		if (type == RuleWeight.TYPE_CHOW || type ==  RuleWeight.TYPE_PONG)
		{
			paramBroadCast.putTArray("ting_list", getTingList(player));
		}

		player.sendEvent(Config.GAME_EVT_ACTION, paramBroadCast);

		((EXPlayBack)room.playBackData).addActionCommand(player.seat, type, card, from_seat,opcardArray);
	}
	
	public void dealCard(EXRoom owner) {
		for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer)entry.getValue();
			player.cardInhand = owner.card.deal();
			Collections.sort(player.cardInhand);
			if(Global.loggerDebug) {
				Global.logger.info(player + " cardlist:" + player.cardInhand);
			}
			if (owner.config.getInt(Config.ROOM_CONFIG_MAI_NIAO) == 1)
			{
				int maiNiaoOpt = owner.config.getInt(Config.ROOM_CONFIG_MAI_NIAO_OPT);
				//买一马
				if (maiNiaoOpt == 1)
				{
					CardNiao niao = new CardNiao();
					niao.playerId = player.playerid;
					niao.seat = player.seat;
					niao.card = owner.card.pop();
					niao.score = 0;
					player.mai_niao.add(niao);
				}
				//买二马
				else if (maiNiaoOpt == 2)
				{
				    for(int i = 0; i < 2; i++)
					{
						CardNiao niao = new CardNiao();
						niao.playerId = player.playerid;
						niao.seat = player.seat;
						niao.card = owner.card.pop();
						niao.score = 0;
						player.mai_niao.add(niao);
					}
				}
				//罚一马
				else if (maiNiaoOpt == 3)
				{
					if (player.seat == owner.bankerSeat)
					{
						CardNiao niao = new CardNiao();
						niao.playerId = player.playerid;
						niao.seat = player.seat;
						niao.card = owner.card.pop();
						niao.score = 0;
						player.mai_niao.add(niao);
					}
				}
				//罚二马
				else if (maiNiaoOpt == 4)
				{
					if (player.seat == owner.bankerSeat)
					{
						for(int i = 0; i < 2; i++)
						{
							CardNiao niao = new CardNiao();
							niao.playerId = player.playerid;
							niao.seat = player.seat;
							niao.card = owner.card.pop();
							niao.score = 0;
							player.mai_niao.add(niao);
						}
                    }
				}
			}
			ITObject param = new TObject();
			ITArray handCard = Util.toTArray(player.cardInhand);
			param.putTArray("card_list", handCard);
			param.putInt("bank_seat", player.room.bankerSeat);
			param.putInt("laiziCard", owner.card.laiziCard);
			param.putInt("laiziCard2", owner.card.laiziCard2);
			param.putInt("laiziCardBefore", owner.card.laiziCardBefore);
			param.putInt("laiziCard2Before", owner.card.laiziCard2Before);
			player.sendEvent(Config.GAME_EVT_PLAYER_DEAL, param);
			player.stateMachine.changeState(Global.getState(PlayerWaitState.class));
		}
	}
	
	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;
		owner.sendEvent(Config.GAME_EVT_DISCARD_TIP, null);
	}
	
	public void winEvent(EXPlayer owner,int from_seat,int win_card) {
		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("win_card", win_card);
		param.putInt("from_seat", from_seat);
		ITArray array = CardUtil.toMPData_WinMap(owner.winMap);
		if (array != null) {
			param.putTArray("win_list", array);
		}
		if(Global.loggerDebug) {
			Global.logger.info(owner + " hupai!["+(owner.seat == from_seat?"self":"other")+"]");
		}
		EXRoom room = owner.getRoom();
		room.broadCastToClient(0, Config.GAME_EVT_HU, param);
		((EXPlayBack)room.playBackData).addWinCardCommand(owner.seat, false);
	}
	
	public void sendNiaoEvt(EXPlayer owner, int seat) {
		EXRoom room = owner.getRoom();
		ITObject param = new TObject();
//		param.putInt("playerid", owner.playerid);
		ITArray array = new TArray();
		for (int index = 0; index < room.niao.size(); index++) {
			array.addTObject(room.niao.get(index).toMP());
		}
		param.putTArray("niao", array);
		param.putInt("start_seat", seat);

		room.broadCastToClient(0, Config.GAME_EVT_NIAO, param);
		((EXPlayBack)room.playBackData).addNiaoCommand(owner.seat, param);
	}

	public void sendMaiNiaoEvt(EXPlayer owner, int seat) {
		EXRoom room = owner.getRoom();
		ITObject param = new TObject();
		ITArray array = new TArray();
		for (Entry<Integer, Player> entry : room.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer) entry.getValue();
			for (int index = 0; index < player.mai_niao.size(); index++) {
				array.addTObject(player.mai_niao.get(index).toMP());
			}
		}

		param.putTArray("mai_niao", array);
		param.putInt("start_seat", seat);

		room.broadCastToClient(0, Config.GAME_EVT_MAI_NIAO, param);
		((EXPlayBack)room.playBackData).addMaiNiaoCommand(owner.seat, param);
	}
	
	/**
	 * Ʊ����ʾ
	 * @param owner
	 */
	public void piaoNiaoTipEvent(EXPlayer owner) {
		owner.sendEvent(Config.GAME_EVT_PIAONIAO_TIP, null);
	}
	
	private ITObject getRoomResultData(EXRoom owner) {
		ITObject mp = TObject.newInstance();
		mp.putBoolean("liuju", owner.liuju);
		mp.putInt("active_player", owner.playerMapBySeat.get(owner.activeSeat).playerid);
		mp.putInt("xipai_score", owner.xi_pai_score);
		long time = System.currentTimeMillis();
		long t = time / 1000;
		mp.putLong("time", t);
		ITArray niao = new TArray();
		for (int index = 0; index < owner.niao.size(); index++) {
			niao.addTObject(owner.niao.get(index).toMP());
		}
		mp.putTArray("niao", niao);
		mp.putTArray("left_card", Util.toTArray(owner.card.cardList));
		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.putInt("piao", player.piao);
			param.putBoolean("is_win", player.winer == 1);
			param.putInt("hu_score", player.score.round_log.get(EXScore.WIN));
			param.putInt("niao_score", player.score.round_log.get(EXScore.NIAO));
			param.putInt("gang_score", player.score.round_log.get(EXScore.KONG));
			param.putInt("piao_niao_score", player.score.round_log.get(EXScore.PIAO_NIAO));
			param.putInt("geng_zhuan", player.score.round_log.get(EXScore.GENG_ZHUAN));
			param.putInt("ma_geng_gong", player.score.round_log.get(EXScore.MA_GENG_GONG));
			if ((owner.config.getBoolean(Config.ROOM_CONFIG_JIEJIEGAO) || owner.config.getBoolean(Config.ROOM_CONFIG_LIAN_ZHUANG)) && player.repeat_win > 0)
			{
				param.putInt("repeat_win", player.repeat_win);
			}
			else
			{
				param.putInt("repeat_win", 0);
			}

			param.putInt("mai_niao_score", player.score.round_log.get(EXScore.MAI_NIAO));
			player.hp_info(param);
			param.putInt("round_score", player.score.round_score);
			param.putInt("total_score", player.score.total_score);
			ITArray handCard = Util.toTArray(player.cardInhand);
			param.putTArray("hand_card", handCard);
			ITArray array = CardUtil.toMPData_WinMap(player.winMap);
			if (array != null) {
				param.putTArray("win_list", array);
			}
			ITArray mai_niao = new TArray();
			for (int index = 0; index < player.mai_niao.size(); index++) {
				mai_niao.addTObject(player.mai_niao.get(index).toMP());
			}
			param.putTArray("mai_niao", mai_niao);
			param.putInt("ming_gang_num", player.ming_gang_num);
			param.putInt("an_gang_num", player.an_gang_num);
			param.putInt("dian_gang_num", player.dian_gang_num);
			ITArray opCardList = TArray.newInstance();

			for (OpCard opCard : player.opCardList) {
				ITObject obj = TObject.newInstance();
				obj.putInt("type", opCard.type);
				obj.putInt("card", opCard.card);
				if(opCard.opCard!=null) {
					obj.putTArray("opcard", opCard.opCard);
				}
				opCardList.addTObject(obj);
			}
			param.putTArray("opCardList", opCardList);

			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.playBackData.addResult(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();
		for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer) entry.getValue();
			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.playBackData.addResult(result);
			mp.putTObject("result", result);
		}
		mp.putTObject("total_result", data);
		
		owner.broadCastToClient(0, Config.GAME_EVT_RESULT1, mp);
		
	}

	/**
	 * 票鸟提示
	 * @param owner
	 */
	public void piaoTipEvent(EXPlayer owner,int reload) {
		ITObject response = new TObject();
		response.putInt("piao", owner.room.config.getInt(Config.ROOM_CONFIG_PIAO));
		response.putInt("last_piao", owner.last_piao);
		response.putInt("last_winer", owner.last_winer);
		response.putInt("reload", reload);
		owner.sendEvent(Config.GAME_EVT_PIAO_TIP, response);
	}

	/**
	 * 票鸟事件
	 * @param owner
	 */
	public void piaoEvent(EXPlayer owner) {
		if(owner.piao==-1)return;

		ITObject param = new TObject();
		param.putInt("seat", owner.seat);
		param.putInt("piao", owner.piao);
		owner.room.broadCastToClient(0, Config.GAME_EVT_PIAO, param);
	}

	public boolean isTingPai(EXPlayer player, int drawCard, List<Integer> delPai, List<OpCard> opCards)
	{
		EXRoom room = player.getRoom();

		List<Integer> tempList = new ArrayList<Integer>();
		for (int index = 1; index <= 8; index++) {
			tempList.add(100*index + 1);
			tempList.add(100*index + 2);
			tempList.add(100*index + 3);
		}
		HashMap<Integer, WinCardType> map = new HashMap<Integer, WinCardType>();
		List<Integer> tempCardList = new ArrayList<Integer>();
		tempCardList.addAll(player.cardInhand);
		if (drawCard > 0)
		{
			Util.removeCard(tempCardList, drawCard, 1);
		}
		if (delPai != null)
		{
			for(int i = 0; i < delPai.size(); i++)
			{
				Util.removeCard(tempCardList, delPai.get(i), 1);
			}
		}

		for(int j = 0; j < tempList.size(); j++)
		{
			int laizi = room.config.getInt(Config.ROOM_CONFIG_LAIZI);
			map.clear();
			WinCard win = new WinCard(tempCardList, tempList.get(j), room.card.laiziCard, room.card.laiziCard2, laizi > 0 ? true : false, true, true);
			if (win.checkWinOpList(map, player, opCards, room, true)) {
			    return true;
			}
		}

		return false;
	}

	public ITArray getTingList(EXPlayer player)
	{
		EXRoom room = player.getRoom();

		Map<Integer, ITArray> cardMap = new HashMap<>();
		List<Integer> tempList = new ArrayList<Integer>();
		for (int index = 1; index <= 8; index++) {
			tempList.add(100*index + 1);
			tempList.add(100*index + 2);
			tempList.add(100*index + 3);
		}
		HashMap<Integer, WinCardType> map = new HashMap<Integer, WinCardType>();

		for(int i = 0; i < player.cardInhand.size(); i++)
		{
			int tempCard = player.cardInhand.get(i);
			if (player.getRoom().isLaizi(tempCard))
			{
				continue;
			}

			List<Integer> tempCardList = new ArrayList<Integer>();
			tempCardList.addAll(player.cardInhand);
			Util.removeCard(tempCardList, tempCard, 1);

			for(int j = 0; j < tempList.size(); j++)
			{
				int laizi = room.config.getInt(Config.ROOM_CONFIG_LAIZI);
				map.clear();
				WinCard win = new WinCard(tempCardList, tempList.get(j), room.card.laiziCard, room.card.laiziCard2, laizi > 0 ? true : false, true, true);
				if (win.checkWin(map, player, room, true)) {
					if (!cardMap.containsKey(tempCard))
					{
						ITArray cardMapList = new TArray();
						cardMapList.addInt(tempList.get(j));
						cardMap.put(tempCard, cardMapList);
					}
					else
					{
						ITArray cardMapList = cardMap.get(tempCard);
						cardMapList.addInt(tempList.get(j));
					}
				}
			}
		}

		ITArray array = TArray.newInstance();
		for (Map.Entry<Integer, ITArray> entry : cardMap.entrySet()) {
			ITObject obj = TObject.newInstance();
			obj.putInt("card", entry.getKey());
			obj.putTArray("value", entry.getValue());
			Global.logger.info("del card:"+entry.getKey()+" hu card:"+ entry.getValue().toJson());
			array.addTObject(obj);
		}

		return array;
	}
}
