package com.game.data;

import com.game.ActionEvent;
import com.game.Global;
import com.game.MainServer;
import com.game.player.state.PlayerPopupState;
import com.game.player.state.PlayerReloadState;
import com.game.state.StateMachine;
import com.taurus.core.entity.ITObject;
import com.taurus.core.entity.TObject;
import com.taurus.core.util.StringUtil;
import com.taurus.permanent.TPServer;
import com.taurus.permanent.data.Session;

/**
 * 基本玩家对象
 * 
 *
 */
public class Player {
	/**
	 * 所在房间对象
	 */
	public Room room = null;
	/**
	 * 用户id
	 */
	public int playerid = 0;

	public String ip = null;
	/**
	 * redis session id
	 */
	public String session_id = StringUtil.Empty;
	public String score_key = StringUtil.Empty;
	public String net_key = StringUtil.Empty;
	/**
	 * 玩家状态机
	 */
	public StateMachine stateMachine = null;

	/**
	 * mpnet session
	 */
	public volatile Session sender = null;
	/**
	 * 是否正在链接
	 */
	public volatile boolean isConnect = false;
	/**
	 * 是否是重连
	 */
	public boolean isReload = false;
	/**
	 * 是否被摧毁
	 */
	public volatile boolean isDestroy = false;

	/**
	 * 当前座位号
	 */
	public int seat = 0;
	public int nextSeat = 0;
	public int lastSeat = 0;
	/**
	 * 昵称
	 */
	public String nick = StringUtil.Empty;
	/**
	 * 性别
	 */
	public int sex = 1;
	/**
	 * 头像
	 */
	public String portrait = StringUtil.Empty;
	/**
	 * GPS位置
	 */
	public String gps_pos = StringUtil.Empty;

	/**
	 * 0 无 1 胡 2 输
	 */
	public int winer = 0;

	/**
	 * 胡牌统计
	 */
	public int winCount = 0;
	/**
	 * 准备状态
	 */
	public boolean ready = false;

	public boolean is_white = false;

	public int black_white_status = 0;

	public double black_white_rate = 10;

	/**
	 * 解散房间状态
	 */
	public int dismissState = 0;
	/**
	 * 申请解散次数
	 */
	public int dismissCount = 0;
	/**
	 * 计分统计
	 */
	public Score score;
	/**
	 * action计时器
	 */
	public Timer actionTimer;
	/**
	 * 计时器
	 */
	public Timer timer;
	public volatile long offlineTime;
	/**
	 * 抽水值
	 */
	public int practicalHpPump = 0;
	
	/**
	 * 抽水实际值
	 */
	public int practicalHpPumpReal = 0;
	/**
	 * 奖励数据
	 */
	public String prs = StringUtil.Empty;
	/**
	 * 托管
	 */
	public volatile boolean entrust = false;
	/**
	 * 自动出牌
	 */
	public volatile boolean manualAutoCard = false;
	/**
	 * 是否正在观看
	 */
	public volatile boolean spectator = false;
	/**
	 * 已玩局数
	 */
	public int already_round = 0;
	/**
	 * 体力值
	 */
	public Hp hp;
	/**
	 * 托管局数
	 */
	public int entrust_round = 0;
	/**
	 * 是否检测退出限制
	 */
	public boolean check_exit_limit = true;

	public boolean xi_pai = false;
	/**
	 * 抽水值total
	 */
	public int xi_pai_total = 0;
	
	
	public Player(int playerid, Room table, String session_id) {
		this.room = table;
		this.playerid = playerid;
		this.session_id = session_id;
		this.score_key = "score_" + playerid;
		this.net_key = "net_" + playerid;
		this.score = newScore();
		this.stateMachine = new StateMachine(this);
		this.isReload = false;
		this.hp = new Hp();
		this.xi_pai = false;
	}

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

	/**
	 * 设置玩家session
	 * 
	 * @param sender
	 */
	public void setSender(Session sender) {
		// 服务器从崩溃中重启
		if (sender == null) {
			this.isReload = true;
			this.isConnect = false;
			this.stateMachine.changeState(Global.getState(PlayerReloadState.class));
			return;
		}
		if (this.isConnect && this.sender != null && this.sender != sender) {
			Global.sessionMgr.deleteSession(this.sender);
			TPServer.me().getController().disconnect(this.sender);
		}
		// 已经连接
		this.sender = sender;
		Global.sessionMgr.putPlayer(sender, this);
		this.isConnect = true;
		// if (this.stateMachine.curState == null || this.isReload) {
		// this.stateMachine.changeState(Global.getState(PlayerInitState.class));
		this.isReload = false;
		// }
	}

	/**
	 * 计时器,Ps 到某状态自动执行某操作
	 * 
	 * @param time  时间 ms
	 * @param cmd   计时完执行事件
	 * @param param 执行事件参数
	 */
	public void startTimer(int time, String cmd, Object param) {
		stopTimer();
		this.timer = new Timer(time, new Timer.ITaskHandler() {
			@SuppressWarnings("unchecked")
			@Override
			public void doTask(Timer timer) {
				Global.info("{} [{}] Timer Excute ActionEvent [{}] param :{}", Player.this.toString(),
						stateMachine.curState.getClass().getSimpleName(), cmd,
						param == null ? "null" : param.toString());
				stateMachine.curState.execute(Player.this, cmd, 0, param);
			}
		});
		room.addTimer(this.timer);
	}

	/**
	 * 指定时间计时, cmd :timer_auto
	 * 
	 * @param time
	 */
	public void startTimer(int time) {
		startTimer(time, ActionEvent.EVENT_TIMER_AUTO, null);
	}

	/**
	 * 默认配置计时器 time : 1000ms cmd : timer_auto
	 */
	public void startTimer() {
		startTimer(room.def_actionTimer_time, ActionEvent.EVENT_TIMER_AUTO, null);
	}

	public void stopTimer() {
		if (this.timer != null) {
			this.timer.stop();
			this.timer = null;
		}
	}

	/**
	 * 停止所有计时器,如玩家退出某状态时
	 */
	public void stopAllTimer() {
		stopTimer();
		stopActionTimer();
	}

	/**
	 * 托管计时器
	 * 
	 * @param time 单位毫秒
	 */
	public void startActionTimer(int time, Object param) {
		stopActionTimer();
		this.actionTimer = new Timer(time, new Timer.ITaskHandler() {
			@SuppressWarnings("unchecked")
			@Override
			public void doTask(Timer timer) {
				String type = "";
				if (param != null) {
					ITObject netParam = (ITObject) param;
					if (netParam.containsKey("type")) {
						type = netParam.getUtfString("type");
					}
				}
				if (ActionEvent.EVENT_ENTRUST.equals(type) && !entrust) {
					entrust = true;
					Global.gameCtr.updatePlayerEntrust(Player.this);
				}
				Global.info("{} [{}] Entrust Auto Execute ActionEvent", Player.this.toString(),
						stateMachine.curState.getClass().getSimpleName());
				stateMachine.curState.execute(Player.this, ActionEvent.EVENT_TIMER_AUTO, 0, param);
			}
		});
		String type = "";
		int broad = 0;
		if (param != null) {
			ITObject netParam = (ITObject) param;
			if (netParam.containsKey("type")) {
				type = netParam.getUtfString("type");
			}
			if (netParam.containsKey("broad")) {
				broad = netParam.getInt("broad");
			}
		}
		if (ActionEvent.EVENT_ENTRUST.equals(type) && broad == 1) {
			this.actionTimer.parameters.put("param", param);
		}
		room.addTimer(this.actionTimer);
	}

	/**
	 * 
	 * @param time 单位毫秒
	 */
	public void startActionTimer(int time) {
		startActionTimer(time, null);
	}

	public boolean isEntrust() {
		return this.room.isEntrust() && this.entrust;
	}

	/**
	 * 托管.
	 */
	public void startActionTimer() {
		stopActionTimer();
		int lt = getEntrustActionLeftTime();
		if (room.isEntrust() && lt <= 0) {
			ITObject param = TObject.newInstance();
			param.putUtfString("type", ActionEvent.EVENT_ENTRUST);

			if (isEntrust()) {
				param.putInt("broad", 0);
				startActionTimer(this.room.default_entrust_time, param);
			} else {
				param.putInt("broad", 1);
				startActionTimer(this.room.entrustTime, param);
				Global.gameCtr.entrust(Player.this, this.room.entrustTime / 1000);
			}
		}
	}

	public void stopActionTimer() {
		if (this.actionTimer != null) {
			if (this.actionTimer.parameters.containsKey("param")) {
				ITObject param = (ITObject) this.actionTimer.parameters.get("param");
				String type = "";
				if (param != null) {
					ITObject netParam = (ITObject) param;
					if (netParam.containsKey("type")) {
						type = netParam.getUtfString("type");
					}
				}
				if (ActionEvent.EVENT_ENTRUST.equals(type)) {
					Global.gameCtr.cancelEntrust(Player.this);
				}
			}
			this.actionTimer.stop();
			this.actionTimer = null;
		}
	}

	public int getActionLeftTime() {
		if (this.actionTimer != null) {
			return Math.abs(this.actionTimer.getCountdownTime() / 1000);
		}
		return 0;
	}

	public int getEntrustActionLeftTime() {
		if (this.actionTimer != null) {
			if (this.actionTimer.parameters.containsKey("param")) {
				ITObject param = (ITObject) this.actionTimer.parameters.get("param");
				String type = "";
				if (param != null) {
					ITObject netParam = (ITObject) param;
					if (netParam.containsKey("type")) {
						type = netParam.getUtfString("type");
					}
				}
				if (ActionEvent.EVENT_ENTRUST.equals(type)) {
					return Math.abs(this.actionTimer.getCountdownTime() / 1000);
				}
			}
		}
		return 0;
	}

	/**
	 * 返回结果
	 * 
	 * @param params
	 * @param gid
	 * @param error
	 */
	public void response(ITObject params, int gid, int error) {
		if (!this.isConnect)
			return;
		if (error == 0) {
			MainServer.instance.sendResponse(gid, error, params, this.sender);
		} else {
			MainServer.instance.sendResponse(gid, error, null, this.sender);
		}
	}

	/**
	 * 发送事件给客户端
	 * 
	 * @param cmd
	 * @param param
	 */
	public void sendEvent(String cmd, ITObject param) {
		if (!this.isConnect)
			return;
		MainServer.instance.sendEvent(cmd, param, this.sender);
	}

	/**
	 * 获取玩家信息
	 * 
	 * @return
	 */
	public ITObject getInfo() {
		ITObject playerData = new TObject();
		playerData.putInt("aid", this.playerid);
		playerData.putUtfString("nick", this.nick);
		playerData.putInt("sex", this.sex);
		playerData.putUtfString("portrait", this.portrait);
		if (StringUtil.isNotEmpty(gps_pos)) {
			playerData.putUtfString("pos", gps_pos);
		}
		String ip = this.ip;
		if (this.ip == null && this.sender != null) {
			ip = sender.getAddress();
		}
		playerData.putInt("ready", this.ready ? 1 : 0);
		playerData.putUtfString("ip", ip);
		playerData.putInt("seat", this.seat);
		playerData.putInt("online", this.isConnect ? 1 : 0);
		playerData.putBoolean("spectator", spectator);
		if (this.room.openEntrust) {
			playerData.putBoolean("entrust", this.entrust);
			playerData.putInt("entrust_time", getEntrustActionLeftTime());
		}
		hp_info(playerData);
		// if (Redis.use().hexists(this.session_id, "offLineTime")) {
		// int offLineTime = Integer.parseInt(Redis.use().hget(this.session_id,
		// "offLineTime"));
		// playerData.putInt("offLineTime", Utils.differSecond(offLineTime));
		// }
		return playerData;
	}

	public ITObject getReloadInfo(boolean self) {
		ITObject playerData = new TObject();
		playerData.putInt("playerid", playerid);
		if (this.room.openEntrust && this.room.isEntrust) {
			playerData.putBoolean("entrust", this.entrust);
			playerData.putInt("entrust_time", getEntrustActionLeftTime());

			Global.logger.info("entrust_time getEntrustActionLeftTime() : " + getEntrustActionLeftTime());
		}
		playerData.putBoolean("popup", this.stateMachine.curState instanceof PlayerPopupState);
		hp_info(playerData);
		return playerData;
	}

	/**
	 * 玩家销毁时调用
	 * 
	 * @param sysredis
	 */
	public void destroy(boolean sysredis) {
		if (isDestroy)
			return;
		isDestroy = true;
		stopActionTimer();
		this.room.removePlayer(this, sysredis);
		if (this.sender != null) {
			Global.sessionMgr.deleteSession(sender);
		}
	}

	private int __checkSeat(int seat, int count, boolean add) {
		if (seat > this.room.maxPlayers) {
			seat = 1;
		} else if (seat <= 0) {
			seat = this.room.maxPlayers;
		}
		if (count == this.room.maxPlayers)
			return seat;
		Player player = this.room.playerMapBySeat.get(seat);
		if (player == null || player.spectator) {
			if (add)
				seat = seat + 1;
			else
				seat = seat - 1;
			count++;
			return __checkSeat(seat, count, add);
		}
		return seat;
	}

	/**
	 * 初始化座位信息
	 */
	public void initSeat() {
		this.nextSeat = __checkSeat(this.seat + 1, 1, true);
		this.lastSeat = __checkSeat(this.seat - 1, 1, false);
	}

	/**
	 * 清理玩家数据
	 */
	public void clear() {
		this.winer = 0;
		this.check_exit_limit = true;
		this.is_white = false;
		this.manualAutoCard = false;

		stopActionTimer();
	}

	/**
	 * 注册redis事件，总服处理
	 * 
	 * @param type
	 * @param num
	 */
	public void redisEvent(int type, int num) {
		Global.eventCtr.redisEvent(playerid, type, num);
	}

	public String toString() {
		return session_id;
	}

	public void hp_info(ITObject param) {
		ITObject hp_info = TObject.newInstance();
		// 下局体力值
		hp_info.putLong("cur_hp", hp.cur_hp);
		// 本局实际输赢体力值
		hp_info.putInt("round_actual_hp", hp.round_actual_hp);
		// 输赢是否已达上限
		hp_info.putBoolean("upper_limit", hp.upper_limit);
		// 总输赢体力值
		hp_info.putInt("total_hp", hp.total_hp);
		param.putTObject("hp_info", hp_info);

	}

	/**
	 * 获取当前体力值
	 */
	public Long getHp() {
		return this.hp.cur_hp + (long) this.hp.round_actual_hp;
	}

//	public void updateHp() {
//		this.hp.cur_hp = this.hp.cur_hp + this.hp.round_actual_hp;
//	}

	public void clearHp() {
		this.hp.round_actual_hp = 0;
		this.hp.round_answer_hp = 0;
		this.hp.upper_limit = false;
	}

	/**
	 * 设置托管数据
	 * 
	 * @param data
	 */
	public void setEntrustData(ITObject data) {

	}

	public void exitEntrust() {
		if (this.room.isEntrust()) {
			this.entrust_round = 0;
			stopActionTimer();
			this.entrust = false;
			if (room.activeSeat == this.seat) {
				startActionTimer();
			}
		}
	}

	/**
	 * 牌局结束输赢总体力值，包括奖励体力值
	 */
	public int totalHp() {
		return hp.total_hp;
	}

	/**
	 * 需要抽水的具体体力值,不可负分 - 实际赢体力值,可负分 - 实际赢积分 换算成赢总体力值
	 */
	public int hpPumpValue() {
		return hp.total_hp;
	}

}
