package main

import (
	"mongo.games.com/game/model"
	server_proto "mongo.games.com/game/protocol/server"
	"mongo.games.com/game/webapi"
	"mongo.games.com/goserver/core/basic"
	"mongo.games.com/goserver/core/logger"
	"mongo.games.com/goserver/core/task"
	"time"

	"mongo.games.com/goserver/core/module"
)

type QMFlowManager struct {
	BaseClockSinker
	playerStatement    map[int32]map[int32]*webapi.PlayerStatementSrc
	offPlayerStatement map[int32]map[int32]*webapi.PlayerStatementSrc
}

var QMFlowMgr = &QMFlowManager{}

func (this *QMFlowManager) ModuleName() string {
	return "QMFlowManager"
}

func (this *QMFlowManager) Init() {

}

func (this *QMFlowManager) Update() {
	this.Save()
}

func (this *QMFlowManager) Shutdown() {
	this.ForceSave()

	module.UnregisteModule(this)
}

// 感兴趣所有clock event
func (this *QMFlowManager) InterestClockEvent() int {
	return 1 << CLOCK_EVENT_HOUR
}

func (this *QMFlowManager) OnHourTimer() {
	this.AnsySave()
}

// 增加玩家流水统计
// 数据用途: 流水返利，全民代理佣金结算，确保参数计算无误
// totalWin: 总赢取钱(>=0)
// totalLost: 总输的钱(>=0)
func (this *QMFlowManager) AddPlayerStatement(snid, isBind, totalWin, totalLost, gamefreeID int32, platform,
	packageId string, dbGameFree *server_proto.DB_GameFree) {
	if model.GameParamData.CloseQMThr {
		return
	}

	if dbGameFree == nil {
		return
	}

	if totalWin == 0 && totalLost == 0 {
		return
	}
	/*
		if dbGameFree.GetPlayerWaterRate() == 0 {
			return
		}
	*/
	if this.playerStatement == nil {
		this.playerStatement = make(map[int32]map[int32]*webapi.PlayerStatementSrc)
	}
	var gpmap map[int32]*webapi.PlayerStatementSrc
	if gp, exist := this.playerStatement[gamefreeID]; exist {
		gpmap = gp
	} else {
		gpmap = make(map[int32]*webapi.PlayerStatementSrc)
	}

	if ps, exist := gpmap[snid]; exist {
		ps.TotalWin += float64(totalWin*dbGameFree.GetPlayerWaterRate()) / 100
		ps.TotalLose += float64(totalLost*dbGameFree.GetPlayerWaterRate()) / 100
		ps.TotaSrclWin += float64(totalWin)
		ps.TotaSrclLose += float64(totalLost)
	} else {
		ps := &webapi.PlayerStatementSrc{
			Platform:     platform,
			PackageId:    packageId,
			SnId:         snid,
			IsBind:       isBind,
			TotalWin:     float64(totalWin*dbGameFree.GetPlayerWaterRate()) / 100,
			TotalLose:    float64(totalLost*dbGameFree.GetPlayerWaterRate()) / 100,
			TotaSrclWin:  float64(totalWin),
			TotaSrclLose: float64(totalLost),
		}
		gpmap[snid] = ps
	}

	this.playerStatement[gamefreeID] = gpmap
}

// 增加玩家流水统计
// 数据用途: 流水返利，全民代理佣金结算，确保参数计算无误
// totalWin: 总赢取钱(>=0)
// totalLost: 总输的钱(>=0)
func (this *QMFlowManager) AddOffPlayerStatement(snid, totalWin, totalLost, gamefreeID int32, dbGameFree *server_proto.DB_GameFree) {
	if model.GameParamData.CloseQMThr {
		return
	}
	if dbGameFree == nil {
		return
	}
	if totalWin == 0 && totalLost == 0 {
		return
	}
	/*
		if dbGameFree.GetPlayerWaterRate() == 0 {
			return
		}
	*/
	if this.offPlayerStatement == nil {
		this.offPlayerStatement = make(map[int32]map[int32]*webapi.PlayerStatementSrc)
	}
	var gpmap map[int32]*webapi.PlayerStatementSrc
	if gp, exist := this.offPlayerStatement[gamefreeID]; exist {
		gpmap = gp
	} else {
		gpmap = make(map[int32]*webapi.PlayerStatementSrc)
	}

	if ps, exist := gpmap[snid]; exist {
		ps.TotalWin += float64(totalWin*dbGameFree.GetPlayerWaterRate()) / 100
		ps.TotalLose += float64(totalLost*dbGameFree.GetPlayerWaterRate()) / 100
		ps.TotaSrclWin += float64(totalWin)
		ps.TotaSrclLose += float64(totalLost)
	} else {
		ps := &webapi.PlayerStatementSrc{
			SnId:         snid,
			TotalWin:     float64(totalWin*dbGameFree.GetPlayerWaterRate()) / 100,
			TotalLose:    float64(totalLost*dbGameFree.GetPlayerWaterRate()) / 100,
			TotaSrclWin:  float64(totalWin),
			TotaSrclLose: float64(totalLost),
		}
		gpmap[snid] = ps
	}

	this.offPlayerStatement[gamefreeID] = gpmap
}

// 异步保存，用户每个小时的定时处理
func (this *QMFlowManager) AnsySave() {
	//先查找一下不在线的玩家，看是否在线,先保存一次
	tempSave := this.offPlayerStatement
	this.offPlayerStatement = nil

	task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
		for _, v := range tempSave {
			for m, n := range v {
				baseInfo := model.GetPlayerBaseInfo(n.Platform, m)
				if baseInfo != nil {
					n.Platform = baseInfo.Platform
					n.PackageId = baseInfo.PackageID
					isBind := int32(0)
					if baseInfo.Tel != "" {
						isBind = 1
					}
					n.IsBind = isBind
				}
			}
		}
		return nil
	}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
		for k, v := range tempSave {
			for m, n := range v {
				if n.Platform != "" {
					isQuMin := false
					//pt := PlatformMgrSingleton.GetPackageTag(n.PackageId)
					//if pt != nil && pt.SpreadTag == 1 {
					//	isQuMin = true
					//}
					if !isQuMin && model.GameParamData.QMOptimization {
						//不是全民包，不发送对应的数据
						delete(v, m)
						continue
					}
					if this.playerStatement == nil {
						this.playerStatement = make(map[int32]map[int32]*webapi.PlayerStatementSrc)
					}
					var gpmap map[int32]*webapi.PlayerStatementSrc
					if gp, exist := this.playerStatement[k]; exist {
						gpmap = gp
					} else {
						gpmap = make(map[int32]*webapi.PlayerStatementSrc)
					}

					if ps, exist := gpmap[m]; exist {
						ps.TotalWin += n.TotalWin
						ps.TotalLose += n.TotalLose
						ps.TotaSrclWin += n.TotaSrclWin
						ps.TotaSrclLose += n.TotaSrclLose
					} else {
						ps := &webapi.PlayerStatementSrc{
							SnId:         n.SnId,
							TotalWin:     n.TotalWin,
							TotalLose:    n.TotalLose,
							TotaSrclWin:  n.TotaSrclWin,
							TotaSrclLose: n.TotaSrclLose,
							PackageId:    n.PackageId,
							Platform:     n.Platform,
							IsBind:       n.IsBind,
						}
						gpmap[m] = ps
					}

					this.playerStatement[k] = gpmap
					delete(v, m)
				} else {
					//没有找到对应的用户信息，可能是数据库出现问题，重新插入数据
					logger.Logger.Errorf("save player qm err:%v,%v,%v,%v,%v,%v", n.SnId, n.TotaSrclLose, n.TotaSrclWin,
						n.TotalLose, n.TotalWin, m)
					if this.offPlayerStatement == nil {
						this.offPlayerStatement = make(map[int32]map[int32]*webapi.PlayerStatementSrc)
					}
					var gpmap map[int32]*webapi.PlayerStatementSrc
					if gp, exist := this.offPlayerStatement[k]; exist {
						gpmap = gp
					} else {
						gpmap = make(map[int32]*webapi.PlayerStatementSrc)
					}

					if ps, exist := gpmap[m]; exist {
						ps.TotalWin += n.TotalWin
						ps.TotalLose += n.TotalLose
						ps.TotaSrclWin += n.TotaSrclWin
						ps.TotaSrclLose += n.TotaSrclLose
					} else {
						ps := &webapi.PlayerStatementSrc{
							SnId:         n.SnId,
							TotalWin:     n.TotalWin,
							TotalLose:    n.TotalLose,
							TotaSrclWin:  n.TotaSrclWin,
							TotaSrclLose: n.TotaSrclLose,
							PackageId:    n.PackageId,
							Platform:     n.Platform,
							IsBind:       n.IsBind,
						}
						gpmap[m] = ps
					}

					this.offPlayerStatement[k] = gpmap
				}
			}
		}
	}), "QMFlowManagerAnsySave").Start()
}

// 强制保存，在关闭时调用
func (this *QMFlowManager) ForceSave() {
	//先查找一下不在线的玩家，看是否在线,先保存一次
	tempSave := this.offPlayerStatement
	this.offPlayerStatement = nil
	for _, v := range tempSave {
		for m, n := range v {
			baseInfo := model.GetPlayerBaseInfo(n.Platform, m)
			if baseInfo != nil {
				n.Platform = baseInfo.Platform
				n.PackageId = baseInfo.PackageID
				isBind := int32(0)
				if baseInfo.Tel != "" {
					isBind = 1
				}
				n.IsBind = isBind
			}
		}
	}

	for k, v := range tempSave {
		for m, n := range v {
			if n.Platform != "" {
				isQuMin := false
				//pt := PlatformMgrSingleton.GetPackageTag(n.PackageId)
				//if pt != nil && pt.SpreadTag == 1 {
				//	isQuMin = true
				//}
				if !isQuMin && model.GameParamData.QMOptimization {
					//不是全民包，不发送对应的数据
					delete(v, m)
					continue
				}
				if this.playerStatement == nil {
					this.playerStatement = make(map[int32]map[int32]*webapi.PlayerStatementSrc)
				}
				var gpmap map[int32]*webapi.PlayerStatementSrc
				if gp, exist := this.playerStatement[k]; exist {
					gpmap = gp
				} else {
					gpmap = make(map[int32]*webapi.PlayerStatementSrc)
				}

				if ps, exist := gpmap[m]; exist {
					ps.TotalWin += n.TotalWin
					ps.TotalLose += n.TotalLose
					ps.TotaSrclWin += n.TotaSrclWin
					ps.TotaSrclLose += n.TotaSrclLose
				} else {
					ps := &webapi.PlayerStatementSrc{
						SnId:         n.SnId,
						TotalWin:     n.TotalWin,
						TotalLose:    n.TotalLose,
						TotaSrclWin:  n.TotaSrclWin,
						TotaSrclLose: n.TotaSrclLose,
						PackageId:    n.PackageId,
						Platform:     n.Platform,
						IsBind:       n.IsBind,
					}
					gpmap[m] = ps
				}

				this.playerStatement[k] = gpmap
				delete(v, m)
			} else {
				//没有找到对应的用户信息，可能是数据库出现问题，重新插入数据
				logger.Logger.Errorf("save player qm err:%v,%v,%v,%v,%v,%v", n.SnId, n.TotaSrclLose, n.TotaSrclWin,
					n.TotalLose, n.TotalWin, m)
			}
		}
	}

	logger.Logger.Tracef("ready save flow record:%v", len(this.playerStatement))
	//for gamefreeId, info := range this.playerStatement {
	//	var datas []*webapi.PlayerStatement
	//
	//	for _, ps := range info {
	//
	//		tps := &webapi.PlayerStatement{
	//			Platform:     ps.Platform,
	//			IsBind:       ps.IsBind,
	//			PackageId:    ps.PackageId,
	//			TotalWin:     int32(ps.TotalWin),
	//			TotalLose:    int32(ps.TotalLose),
	//			TotaSrclLose: int32(ps.TotaSrclLose),
	//			TotaSrclWin:  int32(ps.TotaSrclWin),
	//			SnId:         ps.SnId,
	//		}
	//		datas = append(datas, tps)
	//	}
	//
	//	QPT := int(model.GameParamData.SpreadAccountQPT)
	//	//每X条一次，避免GET请求头超长
	//	for len(datas) >= QPT {
	//		d := datas[:QPT]
	//		LogChannelSingleton.WriteMQData(model.GenerateSpreadAccount(common.GetAppId(), gamefreeId, d))
	//	}
	//
	//	if len(datas) != 0 {
	//		d := datas[:]
	//		LogChannelSingleton.WriteMQData(model.GenerateSpreadAccount(common.GetAppId(), gamefreeId, d))
	//	}
	//}
	logger.Logger.Tracef("save all qmflow ok")
	this.playerStatement = nil
}

func (this *QMFlowManager) Save() {
	//先查找一下不在线的玩家，看是否在线,先保存一次
	for k, v := range this.offPlayerStatement {
		for m, n := range v {
			player := PlayerMgrSington.GetPlayerBySnId(m)
			if player != nil {
				isQuMin := false
				//pt := PlatformMgrSingleton.GetPackageTag(player.PackageID)
				//if pt != nil && pt.SpreadTag == 1 {
				//	isQuMin = true
				//}
				if !isQuMin && model.GameParamData.QMOptimization {
					//不是全民包，不发送对应的数据
					delete(v, m)
					continue
				}

				isBind := int32(0)
				if player.Tel != "" {
					isBind = 1
				}
				if this.playerStatement == nil {
					this.playerStatement = make(map[int32]map[int32]*webapi.PlayerStatementSrc)
				}
				var gpmap map[int32]*webapi.PlayerStatementSrc
				if gp, exist := this.playerStatement[k]; exist {
					gpmap = gp
				} else {
					gpmap = make(map[int32]*webapi.PlayerStatementSrc)
				}

				if ps, exist := gpmap[m]; exist {
					ps.TotalWin += n.TotalWin
					ps.TotalLose += n.TotalLose
					ps.TotaSrclWin += n.TotaSrclWin
					ps.TotaSrclLose += n.TotaSrclLose
				} else {
					ps := &webapi.PlayerStatementSrc{
						SnId:         n.SnId,
						TotalWin:     n.TotalWin,
						TotalLose:    n.TotalLose,
						TotaSrclWin:  n.TotaSrclWin,
						TotaSrclLose: n.TotaSrclLose,
						PackageId:    player.PackageID,
						Platform:     player.Platform,
						IsBind:       isBind,
					}
					gpmap[m] = ps
				}

				this.playerStatement[k] = gpmap
				delete(v, m)
			}
		}
	}

	//for gamefreeId, info := range this.playerStatement {
	//	var datas []*webapi.PlayerStatement
	//
	//	for _, ps := range info {
	//
	//		tps := &webapi.PlayerStatement{
	//			Platform:     ps.Platform,
	//			IsBind:       ps.IsBind,
	//			PackageId:    ps.PackageId,
	//			TotalWin:     int32(ps.TotalWin),
	//			TotalLose:    int32(ps.TotalLose),
	//			TotaSrclLose: int32(ps.TotaSrclLose),
	//			TotaSrclWin:  int32(ps.TotaSrclWin),
	//			SnId:         ps.SnId,
	//		}
	//		datas = append(datas, tps)
	//
	//	}
	//
	//	QPT := int(model.GameParamData.SpreadAccountQPT)
	//	//每X条一次，避免GET请求头超长
	//	for len(datas) >= QPT {
	//		d := datas[:QPT]
	//		LogChannelSingleton.WriteMQData(model.GenerateSpreadAccount(common.GetAppId(), gamefreeId, d))
	//		datas = datas[QPT:]
	//	}
	//
	//	//把剩下的记录在推一遍
	//	if len(datas) != 0 {
	//		d := datas[:]
	//		LogChannelSingleton.WriteMQData(model.GenerateSpreadAccount(common.GetAppId(), gamefreeId, d))
	//	}
	//}

	this.playerStatement = nil
}

func init() {
	module.RegisteModule(QMFlowMgr, time.Minute*3, 0)
	ClockMgrSington.RegisteSinker(QMFlowMgr)
}
