package tienlen

import (
	"math/rand"
	"strconv"
	"time"

	rule "mongo.games.com/game/gamerule/tienlen"
	"mongo.games.com/game/gamesrv/base"
	"mongo.games.com/game/proto"
	"mongo.games.com/game/protocol/tienlen"
)

// 玩家身上的额外数据
type TienLenPlayerData struct {
	*base.Player                                //玩家信息
	cards               [rule.HandCardNum]int32 //手牌信息
	delCards            [][]int32               //出过的手牌
	bombScore           int64                   //炸弹得分
	bombTaxScore        int64                   //炸弹税收
	isPass              bool                    //小轮标记过牌
	isDelAll            bool                    //出完牌了
	robotGameTimes      int32                   //机器人局数限制
	winCoin             int64                   //本局赢的钱
	odds                int32                   // 调控概率
	bombRankScore       int64                   // 排位炸弹积分
	tianHu              int32                   // 天胡类型
	ThinkLongCnt        int32                   //长考次数
	curHandLimitTimeOut time.Duration           // 出牌时间上限
	isNotOverLastHand   bool                    //手牌不能压过上家出牌标志
	cardScore           int                     // 手牌评分
}

func (this *TienLenPlayerData) init() {
	for i := int32(0); i < rule.HandCardNum; i++ {
		this.cards[i] = rule.InvalideCard
	}
	this.delCards = [][]int32{}
	this.bombScore = 0
	this.bombTaxScore = 0
	this.isPass = false
	this.isDelAll = false
	this.robotGameTimes = rule.RobotGameTimesMin + rand.Int31n(rule.RobotGameTimesMax)
	this.winCoin = 0
	this.odds = 0
	this.bombRankScore = 0
	this.tianHu = 0
	this.ThinkLongCnt = 0
	this.curHandLimitTimeOut = rule.TienLenPlayerOpTimeout
	this.isNotOverLastHand = false
	this.cardScore = 0
}

func (this *TienLenPlayerData) Clear() {
	for i := int32(0); i < rule.HandCardNum; i++ {
		this.cards[i] = rule.InvalideCard
	}
	this.delCards = [][]int32{}
	this.bombScore = 0
	this.bombTaxScore = 0
	this.isPass = false
	this.isDelAll = false
	this.winCoin = 0
	this.odds = 0
	this.bombRankScore = 0
	this.tianHu = 0
	this.ThinkLongCnt = 0
	this.curHandLimitTimeOut = rule.TienLenPlayerOpTimeout
	this.isNotOverLastHand = false

	this.MarkFlag(base.PlayerState_WaitNext)
	this.TestLog = this.TestLog[:0]
}

// CanOp 能否操作
func (this *TienLenPlayerData) CanOp() bool {
	if this.IsGameing() && !this.isPass && !this.isDelAll {
		return true
	}
	return false
}

// TotalOutIn 计算玩家赔率 产出/投入
func (this *TienLenPlayerData) TotalOutIn(gameId int32) (int64, int64) {
	if this.GDatas != nil {
		if d, exist := this.GDatas[strconv.Itoa(int(gameId))]; exist {
			return d.Statics.TotalOut, d.Statics.TotalIn
		}
	}
	return 0, 0
}

// GetThinkLongTime 根据长考次数获取当前出牌时间
func (this *TienLenPlayerData) GetThinkLongTime() time.Duration {
	if this.IsRobot() {
		return rule.TienLenPlayerOpTimeout
	}

	CurThinkLongCnt := this.ThinkLongCnt
	if CurThinkLongCnt < 0 {
		CurThinkLongCnt = 0
	}

	for _, TlValue := range rule.ThinkLongSct {
		if CurThinkLongCnt >= TlValue.Min && CurThinkLongCnt <= TlValue.Max {
			return TlValue.Time
		}
	}

	return rule.TienLenPlayerOpTimeout
}

// RefreshThinkLongCnt 根据出牌时间计算 刷新长考次数
func (this *TienLenPlayerData) RefreshThinkLongCnt(handTime time.Duration, bSetZero bool) {
	if this.IsRobot() {
		return
	}

	CurThingLongTime := this.GetThinkLongTime()

	if bSetZero {
		this.ThinkLongCnt = 0
	} else {
		// 长考时间减去 出牌时间
		second := (CurThingLongTime - handTime) / (time.Second)
		if second <= 5 {
			this.ThinkLongCnt++
		}
	}

	this.SendThinkLongCnt()
}

// SendThinkLongCnt 发送长考次数
func (this *TienLenPlayerData) SendThinkLongCnt() {

	if this.IsRobot() {
		return
	}

	pack := &tienlen.SCTienLenPlayerThinkLongCnt{}

	pack.ThinkLongCnt = this.ThinkLongCnt

	proto.SetDefaults(pack)

	this.SendToClient(int(tienlen.TienLenPacketID_PACKET_SCTienLenThinkLongCnt), pack)
	//logger.Logger.Trace("-------(this *TienLenPlayerData) SendThinkLongCnt player SnId:", this.SnId, ";SCTienLenPlayerThinkLongCnt: ", pack.ThinkLongCnt)
}

// RefreshCurHandLimitTimeOut 刷新玩家出牌时间
func (this *TienLenPlayerData) RefreshCurHandLimitTimeOut() {
	if this.IsRobot() {
		return
	}

	this.curHandLimitTimeOut = this.GetThinkLongTime()
}

func (this *TienLenPlayerData) GetCurHandLimitTimeOut() time.Duration {
	if this.IsRobot() {
		return rule.TienLenPlayerOpTimeout
	}

	return this.curHandLimitTimeOut
}

// EnterAutoState 游戏中 进入自动托管状态
func (this *TienLenPlayerData) EnterAutoState() {
	if this.IsRobot() {
		return
	}

	if this.isNotOverLastHand {
		return
	}

	if this.IsAuto() {
		return
	}

	this.RefreshThinkLongCnt(0, true)

	s := this.GetScene()
	if s != nil {
		if sceneEx, ok := s.GetExtraData().(*TienLenSceneData); ok {
			if sceneEx.GetGaming() {
				this.MarkFlag(base.PlayerState_Auto)
				this.SyncFlag(true)
				//logger.Logger.Trace("(this *TienLenPlayerData) EnterAutoState", " player=", this.Name, " ThinkLongCnt=", this.ThinkLongCnt)
			}
		}
	}
}

// 游戏中 离开自动托管状态
func (this *TienLenPlayerData) LeaveAutoState(s *base.Scene) {
	if this.IsRobot() {
		return
	}

	this.RefreshThinkLongCnt(0, true)

	if _, ok := s.GetExtraData().(*TienLenSceneData); ok {
		this.UnmarkFlag(base.PlayerState_Auto)

		onlyMyself := []bool{true}
		this.SyncFlag(onlyMyself...)
		//logger.Logger.Trace("(this *TienLenPlayerData) LeaveAutoState", " player:", this.SnId, " Flag=", this.GetFlag())
	}
}
