package main

import (
	"fmt"
	"math/rand"
	"time"

	"mongo.games.com/goserver/core/basic"
	"mongo.games.com/goserver/core/logger"
	"mongo.games.com/goserver/core/netlib"
	"mongo.games.com/goserver/core/task"

	"mongo.games.com/game/common"
	"mongo.games.com/game/model"
	"mongo.games.com/game/protocol/bag"
	"mongo.games.com/game/srvdata"
)

// 查看背包
type CSBagInfoPacketFactory struct {
}

type CSBagInfoHandler struct {
}

func (this *CSBagInfoPacketFactory) CreatePacket() interface{} {
	pack := &bag.CSBagInfo{}
	return pack
}

func (this *CSBagInfoHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSBagInfoHandler Process recv ", data)
	if _, ok := data.(*bag.CSBagInfo); ok {
		p := PlayerMgrSington.GetPlayer(sid)
		if p == nil {
			logger.Logger.Warn("CSBagInfoHandler p == nil")
			return nil
		}
		platform := p.GetPlatform()
		if platform == nil {
			return nil
		}
		//nowLocation := int(msg.NowLocation - 1)
		playbag := BagMgrSingleton.GetBagInfo(p.SnId)
		pack := &bag.SCBagInfo{RetCode: bag.OpResultCode_OPRC_Sucess, BagNumMax: BagItemMax}
		if playbag != nil {
			for _, v := range playbag.BagItem {
				item := srvdata.PBDB_GameItemMgr.GetData(v.ItemId)
				if item != nil && v.ItemNum > 0 /*&& (nowLocation == -1 || (nowLocation < len(item.ShowLocation) && item.ShowLocation[nowLocation] == 1))*/ {
					pack.Infos = append(pack.Infos, &bag.ItemInfo{
						ItemId:  v.ItemId,
						ItemNum: v.ItemNum,
						//Name:           item.Name,
						//ShowLocation:   item.ShowLocation,
						//Classify:       item.Classify,
						//Type:           item.Type,
						//Effect0:        item.Effect0,
						//Effect:         item.Effect,
						//SaleType:       item.SaleType,
						//SaleGold:       item.SaleGold,
						//Composition:    item.Composition,
						//CompositionMax: item.CompositionMax,
						//Time:           item.Time,
						//Location:       item.Location,
						//Describe:       item.Describe,
						ObtainTime: v.ObtainTime,
					})
				}
			}
		}
		logger.Logger.Trace("SCBagInfo:", pack)
		p.SendToClient(int(bag.SPacketID_PACKET_ALL_BAG_INFO), pack)
	}
	return nil
}

// 使用/获取道具 PS严格来说客户端只存在消耗道具 服务器增加 上线要禁止该接口增加道具
type CSUpBagInfoPacketFactory struct {
}

type CSUpBagInfoHandler struct {
}

func (this *CSUpBagInfoPacketFactory) CreatePacket() interface{} {
	pack := &bag.CSUpBagInfo{}
	return pack
}

func (this *CSUpBagInfoHandler) Process(s *netlib.Session, packetid int, data interface{}, sid int64) error {
	logger.Logger.Trace("CSUpBagInfoHandler Process recv ", data)
	msg, ok := data.(*bag.CSUpBagInfo)
	if !ok {
		return nil
	}

	p := PlayerMgrSington.GetPlayer(sid)
	if p == nil {
		logger.Logger.Warn("CSUpBagInfoHandler p == nil")
		return nil
	}

	platform := p.GetPlatform()
	if platform == nil {
		return nil
	}

	pack := &bag.SCUpBagInfo{RetCode: bag.OpResultCode_OPRC_Error}
	send := func() {
		p.SendToClient(int(bag.SPacketID_PACKET_ALL_BAG_USE), pack)
		logger.Logger.Tracef("SCUpBagInfo: %v", pack)
	}

	item := BagMgrSingleton.GetItem(p.SnId, msg.ItemId)
	if item == nil || msg.ItemNum <= 0 || item.ItemNum < int64(msg.ItemNum) || len(item.Effect) != ItemMax || p.SnId == msg.AcceptSnId {
		send()
		return nil
	}

	var isCanOp int32
	if msg.NowEffect == 0 { //竖版
		isCanOp = item.Effect0[msg.Opt]
	} else if msg.NowEffect == 1 { //横版
		isCanOp = item.Effect[msg.Opt]
	}

	if isCanOp == 0 {
		logger.Logger.Trace("道具没有操作权限", msg.ItemId)
		send()
		return nil
	}

	ts := time.Now().Unix()

	switch msg.Opt {
	case ItemCanUse:
		logger.Logger.Trace("道具使用", msg.ItemId)

		f := func() {
			// 使用道具，减少道具
			BagMgrSingleton.SalePlayerItem(p, item, int64(msg.ItemNum))
			BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemConsume, item.ItemId, item.Name, int64(msg.ItemNum), "道具使用")
			pack.RetCode = bag.OpResultCode_OPRC_Sucess
			pack.NowItemId = item.ItemId
			pack.NowItemNum = item.ItemNum
		}

		switch item.ItemId {
		case common.ItemIDGiftBox:
			f()
			useFunc := func() {
				sum := 0
				for _, v := range srvdata.PBDB_GiftBoxMgr.Datas.GetArr() {
					sum += int(v.GetRate())
				}
				if sum > 0 {
					n := 0
					i := rand.Intn(sum)
					for _, v := range srvdata.PBDB_GiftBoxMgr.Datas.GetArr() {
						n += int(v.GetRate())
						if i < n {
							var items []*Item
							for k, vv := range v.ItemID {
								if vv > 0 {
									items = append(items, &Item{
										ItemId:     int32(k),
										ItemNum:    vv,
										ObtainTime: ts,
									})
								}
							}
							if len(items) > 0 {
								BagMgrSingleton.AddJybBagInfo(p, items, 0, common.GainWay_ItemUse, "player", "道具使用")
								for _, v := range items {
									data := srvdata.PBDB_GameItemMgr.GetData(v.ItemId)
									if data != nil {
										// 背包变更记录
										BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemObtain, v.ItemId, data.Name, v.ItemNum, "碎片礼盒获得")
									}
									pack.Infos = append(pack.Infos, &bag.ItemInfo{
										ItemId:     v.ItemId,
										ItemNum:    v.ItemNum,
										ObtainTime: v.ObtainTime,
									})
								}
							}
							break
						}
					}
				}
			}
			for i := 0; i < int(msg.ItemNum); i++ {
				useFunc()
			}

		default:
			logger.Logger.Warnf("道具使用未定义", msg.ItemId)
		}

	case ItemCanGive:
		logger.Logger.Trace("道具赠送", msg.ItemId)
		acceptPlayer := PlayerMgrSington.GetPlatformPlayerBySnId(p.Platform, msg.AcceptSnId)
		if acceptPlayer != nil {
			BagMgrSingleton.AddMailByItem(p.Platform, p.SnId, p.Name, msg.AcceptSnId, msg.ShowId, []int32{msg.ItemId, msg.ItemNum})
			BagMgrSingleton.SalePlayerItem(p, item, int64(msg.ItemNum))
			remark := fmt.Sprintf("赠送给玩家(%v)", msg.AcceptSnId)
			BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemConsume, item.ItemId, item.Name, int64(msg.ItemNum), remark)
			logger.Logger.Trace("道具赠送成功", msg.ItemId)
			pack.RetCode = bag.OpResultCode_OPRC_Sucess
			pack.NowItemId = msg.ItemId
			pack.NowItemNum = item.ItemNum
		} else {
			task.New(nil, task.CallableWrapper(func(o *basic.Object) interface{} {
				return model.GetPlayerBaseInfo(p.Platform, msg.AcceptSnId)
			}), task.CompleteNotifyWrapper(func(data interface{}, t task.Task) {
				aPlayer := data.(*model.PlayerBaseInfo)
				if data != nil && aPlayer != nil {
					BagMgrSingleton.AddMailByItem(p.Platform, p.SnId, p.Name, msg.AcceptSnId, msg.ShowId, []int32{msg.ItemId, msg.ItemNum})
					BagMgrSingleton.SalePlayerItem(p, item, int64(msg.ItemNum))
					remark := fmt.Sprintf("赠送给玩家(%v)", msg.AcceptSnId)
					BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemConsume, item.ItemId, item.Name, int64(msg.ItemNum), remark)
					logger.Logger.Trace("道具赠送成功", msg.ItemId)
					pack.RetCode = bag.OpResultCode_OPRC_Sucess
					pack.NowItemId = msg.ItemId
					pack.NowItemNum = item.ItemNum
				} else {
					pack.RetCode = bag.OpResultCode_OPRC_NotPlayer
				}
				send()
			}), "GetPlayerBaseInfo").Start()
			return nil
		}

	case ItemCanSell:
		logger.Logger.Trace("道具出售", msg.ItemId)
		if msg.ItemNum > 0 {
			isF := BagMgrSingleton.SaleItem(p, msg.ItemId, int64(msg.ItemNum))
			if isF {
				pack.RetCode = bag.OpResultCode_OPRC_Sucess
				if item.SaleGold > 0 {
					if item.SaleType == 1 {
						remark := "道具出售" + fmt.Sprintf("%v-%v", msg.ItemId, msg.ItemNum)
						p.AddCoin(int64(item.SaleGold*msg.ItemNum), 0, common.GainWay_Item_Sale, "sys", remark)
						pack.Coin = int64(item.SaleGold * msg.ItemNum)
						BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemConsume, item.ItemId, item.Name, int64(msg.ItemNum), "道具出售")
					} else if item.SaleType == 2 {
						remark := "道具出售" + fmt.Sprintf("%v-%v", msg.ItemId, msg.ItemNum)
						p.AddDiamond(int64(item.SaleGold*msg.ItemNum), 0, common.GainWay_Item_Sale, "sys", remark)
						pack.Diamond = int64(item.SaleGold * msg.ItemNum)
						BagMgrSingleton.RecordItemLog(p.Platform, p.SnId, ItemConsume, item.ItemId, item.Name, int64(msg.ItemNum), "道具出售")
					}
				}
				pack.NowItemId = item.ItemId
				pack.NowItemNum = item.ItemNum
			}
		}
	}

	send()
	return nil
}

func init() {
	// 查看背包
	common.RegisterHandler(int(bag.SPacketID_PACKET_ALL_BAG_INFO), &CSBagInfoHandler{})
	netlib.RegisterFactory(int(bag.SPacketID_PACKET_ALL_BAG_INFO), &CSBagInfoPacketFactory{})

	// 道具操作(赠送，出售...)
	common.RegisterHandler(int(bag.SPacketID_PACKET_ALL_BAG_USE), &CSUpBagInfoHandler{})
	netlib.RegisterFactory(int(bag.SPacketID_PACKET_ALL_BAG_USE), &CSUpBagInfoPacketFactory{})
}
