package extend.mj;

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

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;


/**
 * 
 * 
 */
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);	
	}

	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 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.sendEvent(Config.GAME_EVT_DRAW, param);
		player.cardInhand.add(player.drawCard);
		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;
		player.outcardList.add(discard);
		Util.removeCard(player.cardInhand, discard, 1);
		if(Global.loggerDebug) {
			Global.logger.info(player + " outcard["+discard+"]");
		}
	}
	

	
	public void actionCard(EXPlayer player,int card,int type,int from_seat,ITArray opcardArray,boolean opengang){
		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);
		}
		paramBroadCast.putBoolean("opengang", opengang);
		EXRoom room = player.getRoom();
		if(Global.loggerDebug) {
			Global.logger.info(String.format("%s from_seat:%d card:%d type:%d opengang:%b", player,from_seat,card,type,opengang));
		}
		room.broadCastToClient(0, Config.GAME_EVT_ACTION, paramBroadCast);
		((EXPlayBack)room.playBackData).addActionCommand(player.seat, type, card, from_seat,opcardArray,opengang);
	}
	
	public void dealCard(EXRoom owner) {
		for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
			EXPlayer player = (EXPlayer)entry.getValue();
			//player.cardInhand = owner.card.deal(player, owner.bankerSeat == player.seat?14:13);
			player.cardInhand = owner.card.deal(player.seat,owner.bankerSeat == player.seat?14:13);
			if(owner.bankerSeat == player.seat) {
				player.drawCard = player.cardInhand.get(player.cardInhand.size()-1);
				player.skipDraw = true;
			}
//			Collections.sort(player.cardInhand);
			
			if(Global.loggerDebug) {
				Global.logger.info(player + " cardlist:" + player.cardInhand);
			}
		}
		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));
		}
	}
	
	public void tipEvent(EXPlayer owner) {
		ITObject param = owner.tipMgr.toMP();
		Global.logger.info(param.toJson());
		owner.sendEvent(Config.GAME_EVT_FZTIPS, param);
	}
	
	public void discardTipEvent(EXPlayer owner) {
		owner.getRoom().currenDiscardSeat = owner.seat;
		ITObject param = new TObject();
		param.putBoolean("auto",owner.autoOutCard);
		owner.sendEvent(Config.GAME_EVT_DISCARD_TIP, param);
	}
	
	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);
		ITArray array = CardUtil.toMPData_WinMap(owner.winMap);
		if (array != null) {
			param.putTArray("win_list", array);
		}
		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);
	}
	
	/**
	 * @param owner
	 */
	public void qsTipEvent(EXPlayer owner) {
		ITObject param = owner.tipMgr.toMP();
		ITArray types = null;
		for (Entry<Integer, Tip> entry : owner.tipMgr.tipMap.entrySet()) {
			types = CardUtil.toMPData_WinMap(entry.getValue().winMap);
			break;
		}
		param.putTArray("types", types);
		owner.sendEvent(Config.GAME_EVT_QSTIP, param);
	}
	
	/**
	 * @param owner
	 */
	public void piaoNiaoTipEvent(EXPlayer owner) {
		owner.sendEvent(Config.GAME_EVT_PIAONIAO_TIP, null);
	}
	
	/**
	 * @param owner
	 */
	public void piaoNiaoEvent(EXPlayer owner) {
	//	if(owner.piaoNiao==0)return;
		ITObject param = new TObject();
		param.putInt("seat", owner.seat);
		param.putInt("num", owner.piaoNiao);
		owner.room.broadCastToClient(0, Config.GAME_EVT_PIAONIAO, param);
//		owner.getRoom().playBackData.addPiaoNiaoCommand(owner.seat, owner.piaoNiao);
	}
	
	/**
	 * @param owner
	 */
	public void tingTipEvent(EXPlayer owner) {
		owner.sendEvent(Config.GAME_EVT_TING_TIP, null);
	}
	
	/**
	 * @param owner
	 */
	public void tingEvent(EXPlayer owner) {
		if(!owner.tianting)return;
		ITObject param = new TObject();
		param.putInt("seat", owner.seat);
		owner.room.broadCastToClient(0, Config.GAME_EVT_TING, param);
	}
	
	/**
	 * @param owner
	 * @param types
	 */
	public void qsWinEvent(EXPlayer owner,Tip tip) {
		ITObject param = new TObject();
		ITArray data = CardUtil.toMPData_WinMap(tip.winMap,true);
		param.putTArray("data", data);
		param.putInt("type", tip.group_type);
		param.putInt("seat", owner.seat);
		
		if(Global.loggerDebug) {
			Global.logger.info(owner + (tip.type == RuleWeight.TYPE_QSWIN?" QS":" TZ") + "Win type " + tip.winMap);
		}
		EXRoom room = owner.getRoom();
		int id = owner.qsList.size() + 1;
		QSLog qs_log = new QSLog();
		qs_log.winMap = data;
		owner.qsList.add(qs_log);
		for (Entry<Integer, WinCardType> entry : tip.winMap.entrySet()) {
			WinCardType wct = entry.getValue();
			for(int i = 0;i<wct.value; ++i) {
				room.addQSScore(owner, wct.score,id,qs_log);
			}

			if(wct.type == RuleWeight.TYPE_LIULIUSHUN) {
				for(int i=0;i<wct.opcard.size();++i) {
					owner.llsCardRecord.add(wct.opcard.getInt(i));
				}
			}
		}

		int niao_type = room.config.getInt(Config.ROOM_CONFIG_NIAO_TYPE);
		if(niao_type == Config.NIAO_TYPE_CS2NIAO) {
			room.niao_qsWin(owner,id,qs_log);
			ITArray niao = new TArray();
			for (int index = 0; index < qs_log.niaoList.size(); index++) {
				niao.addTObject(qs_log.niaoList.get(index).toMP());
			}
			param.putTArray("niao", niao);
		}
		
		room.broadCastToClient(0, Config.GAME_EVT_QSWIN, param);
		((EXPlayBack)room.playBackData).addQSWinCardCommand(owner.seat,tip.group_type,data);
	}

	public boolean isDaHu(int type)
	{
		switch (type)
		{
			case WinCardType.QIXIAODUI:
			case WinCardType.JIANGJIANGHU:
			case WinCardType.QINGYISE:
			case WinCardType.PENGPENGHU:
			case WinCardType.GANGSHANGHUA:
			case WinCardType.GANGSHANGPAO:
			case WinCardType.QUANQIUREN:
			case WinCardType.HAIDI:
			case WinCardType.HAIDIPAO:
			case WinCardType.QIANG_GANG_HU:
			case WinCardType.TYPE_TIANHU:
			case WinCardType.TYPE_TIANTINGHU:
			case WinCardType.TYPE_MENQING:
					return true;
			default:
				return false;
		}
	}

	public int getDaHuNum(Map<Integer,WinCardType> map)
	{
		int count = 0;
		for (Entry<Integer, WinCardType> entry : map.entrySet()) {
			WinCardType wct = entry.getValue();
			if (isDaHu(wct.type))
			{
				for(int i = 0;i<wct.value; ++i) {
					count++;
				}
			}
		}
		return count;
	}

	public void banbanWinEvent(EXPlayer owner,Tip tip) {
		ITObject param = new TObject();
		ITArray data = CardUtil.toMPData_WinMap(tip.winMap,true);
		param.putTArray("data", data);
		param.putInt("type", tip.group_type);
		param.putInt("seat", owner.seat);

		if(Global.loggerDebug) {
			Global.logger.info(owner + (tip.type == RuleWeight.TYPE_QSWIN?" QS":" TZ") + "Win type " + tip.winMap);
		}
		EXRoom room = owner.getRoom();
		int id = owner.qsList.size() + 1;
		QSLog qs_log = new QSLog();
		qs_log.winMap = data;
		owner.qsList.add(qs_log);
		for (Entry<Integer, WinCardType> entry : tip.winMap.entrySet()) {
			WinCardType wct = entry.getValue();
			for(int i = 0;i<wct.value; ++i) {
				room.addQSScore(owner, wct.score,id,qs_log);
			}
			if(wct.type == RuleWeight.TYPE_LIULIUSHUN) {
				for(int i=0;i<wct.opcard.size();++i) {
					owner.llsCardRecord.add(wct.opcard.getInt(i));
				}
			}
		}

		int niao_type = room.config.getInt(Config.ROOM_CONFIG_NIAO_TYPE);
		if(niao_type == Config.NIAO_TYPE_CS2NIAO) {
			room.banban_qsWin(owner,id,qs_log);
		}

		room.broadCastToClient(0, Config.GAME_EVT_QSWIN, param);
		((EXPlayBack)room.playBackData).addQSWinCardCommand(owner.seat,tip.group_type,data);
	}
	
	/**
	 * @param player
	 * @param leftCount
	 * @param ok
	 */
	public void openKongEvent(EXPlayer player,int leftCount,OpenKong ok) {
		ITObject param = new TObject();
		param.putTObject( "info", ok.getTObject());
		param.putInt("seat", player.room.activeSeat);
		param.putInt("left_count", leftCount);
		
		if(Global.loggerDebug) {
			Global.logger.info(player + " openkong " + ok.drawList );
		}
		player.room.broadCastToClient(0, Config.GAME_EVT_OPENKONG, param);
		((EXPlayBack)player.getRoom().playBackData).addOpenKongCommand(player.room.activeSeat, leftCount, ok);
	}
	
	/**
	 * @param owner
	 */
	public void haidiTipEvent(EXPlayer owner) {
		owner.sendEvent(Config.GAME_EVT_HAIDITIP, null);
	}
	
	
	private ITObject getRoomResultData(EXRoom owner) {
		ITObject mp = TObject.newInstance();
		mp.putBoolean("liuju", owner.liuju);
		mp.putInt("xipai_score", owner.xi_pai_score);
		if(owner.liuju) {
			for (Entry<Integer, Player> entry : owner.playerMapById.entrySet()) {
				EXPlayer p = (EXPlayer) entry.getValue();
				p.win_count = 0;
			}
		}
		mp.putInt("active_player", owner.playerMapBySeat.get(owner.activeSeat).playerid);
		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);

		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("win_count", player.win_count);
			param.putInt("hu_score", player.score.round_log.get(EXScore.WIN));
			param.putInt("niao_score", player.score.round_log.get(EXScore.NIAO));
			param.putInt("qs_score", player.score.round_log.get(EXScore.QS));
			ITArray qs_info_list = TArray.newInstance();
			for(QSLog log : player.qsList) {
				qs_info_list.addTObject(log.toMP());
			}
			param.putTArray("qs_info_list", qs_info_list);
			param.putInt("piao_niao_score", player.score.round_log.get(EXScore.PIAO_NIAO));
			param.putBoolean("fengding", player.fengding);
			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);
			}
			player.hp_info(param);
			infoList.addTObject(param);
		}
		mp.putTArray("info_list", infoList);
		return mp;
	}
	
	/**
	 * @param owner
	 */
	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);
	}
	
	/**
	 * @param owner
	 * @param dissmiss
	 */
	public void roomTotalResult(EXRoom owner,boolean dissmiss) {
		ITObject data = TObject.newInstance();
		long t = System.currentTimeMillis() / 1000;
		data.putLong("time", t);
		
		
		ITObject mp = TObject.newInstance();
		mp.putInt("type", dissmiss?2:1);
		if(!dissmiss) {
			ITObject result = getRoomResultData(owner);
			owner.playBackData.addResult(result);
			mp.putTObject("result", result);
		}
		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);
		mp.putTObject("total_result", data);
		
		owner.broadCastToClient(0, Config.GAME_EVT_RESULT1, mp);
		
	}
}
