package models

// roll房奖池
import (
	"box-gm/utils"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"sync"

	"github.com/astaxie/beego"
	"github.com/astaxie/beego/validation"
	"github.com/garyburd/redigo/redis"
)

type RollAwardInfo struct {
	Id         int   `json:"id"`         // 奖池ID
	ItemIdList []int `json:"itemIdList"` // 奖励列表
}

type RollAwardInfoArray []*RollAwardInfo

var rollAwardList RollAwardInfoArray
var raMutex sync.Mutex
var ROLL_AWARD_MAIN_KEY = "roll:award"

// 创建奖池ID
func CreateRollAwardId() int {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		fmt.Println("get redis pool fail")
		return 0
	}
	rd := pool.Get()
	if rd == nil {
		fmt.Println("get redis conn fail")
		return 0
	}
	defer rd.Close()

	reply, err := rd.Do("hincrby", "global", "max:roll:award:id", 1)
	if err != nil {
		fmt.Printf("redis hincrby err: %v", err)
		return 0
	}
	id, err := redis.Int(reply, err)
	if err != nil {
		fmt.Printf("redis hincrby err: %v", err)
		return 0
	}
	return id
}

// 初始化roll房奖池
func InitRollAwardInfo() {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		fmt.Println("get redis pool fail")
		return
	}
	rd := pool.Get()
	defer rd.Close()

	reply, err := rd.Do("hgetall", ROLL_AWARD_MAIN_KEY)
	if err != nil {
		log.Printf("InitRollAwardInfo err:%v", err)
		return
	}
	vals, err := redis.Values(reply, err)
	if err != nil {
		log.Printf("InitRollAwardInfo err:%v", err)
		return
	}

	for i := 0; i < len(vals)/2; i++ {
		id := utils.StringToInt(string(vals[i*2].([]byte)))
		var itemIdList []int
		err = json.Unmarshal(vals[i*2+1].([]byte), &itemIdList)
		if err != nil {
			log.Printf("InitRollAwardInfo err:%v", err)
			return
		}

		rollAwardList = append(rollAwardList, &RollAwardInfo{
			Id:         id,
			ItemIdList: itemIdList,
		})
		log.Printf("InitRollAwardInfo id[%d] itemIdList[%v]", id, itemIdList)
	}

	beego.Info("load roll award info", len(rollAwardList))
}

func checkRollAwardInfo(hf *RollAwardInfo) (err error) {
	valid := validation.Validation{}
	b, _ := valid.Valid(&hf)
	if !b {
		for _, err := range valid.Errors {
			log.Println(err.Key, err.Message)
			return errors.New(err.Message)
		}
	}
	return nil
}

// 新增roll房奖池
func AddRollAwardInfo(hf *RollAwardInfo) error {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		return fmt.Errorf("get redis pool fail")
	}
	rd := pool.Get()
	defer rd.Close()

	if err := checkRollAwardInfo(hf); err != nil {
		return err
	}
	if hf.Id == 0 {
		hf.Id = CreateRollAwardId()
	}
	if hf.Id == 0 {
		return fmt.Errorf("分配奖池ID失败")
	}

	items, err := json.Marshal(hf.ItemIdList)
	if err != nil {
		return err
	}
	rd.Do("hset", ROLL_AWARD_MAIN_KEY, hf.Id, items)

	raMutex.Lock()
	rollAwardList = append(rollAwardList, hf)
	raMutex.Unlock()

	return nil
}

// 修改roll房奖池
func UpdateRollAwardInfo(hf *RollAwardInfo) error {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		return fmt.Errorf("get redis pool fail")
	}
	rd := pool.Get()
	defer rd.Close()

	if err := checkRollAwardInfo(hf); err != nil {
		return err
	}

	items, err := json.Marshal(hf.ItemIdList)
	if err != nil {
		return err
	}
	rd.Do("hset", ROLL_AWARD_MAIN_KEY, hf.Id, items)

	raMutex.Lock()
	for i := 0; i < len(rollAwardList); i++ {
		if hf.Id == rollAwardList[i].Id {
			old := rollAwardList[i]

			old.ItemIdList = hf.ItemIdList
			break
		}
	}
	raMutex.Unlock()

	return nil

}

// 删除roll房奖池
func DelRollAwardInfoById(id int) error {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		return fmt.Errorf("get redis pool fail")
	}
	rd := pool.Get()
	defer rd.Close()

	raMutex.Lock()
	defer raMutex.Unlock()

	_, err := rd.Do("hdel", ROLL_AWARD_MAIN_KEY, id)
	if err != nil {
		log.Println(err)
		return err
	}

	for i := 0; i < len(rollAwardList); i++ {
		if id == rollAwardList[i].Id {
			ii := i + 1
			rollAwardList = append(rollAwardList[:i], rollAwardList[ii:]...)
		}
	}

	return nil
}

// 获取roll房奖池信息
func GetRollAwardInfoById(id int) (hf *RollAwardInfo) {
	raMutex.Lock()
	defer raMutex.Unlock()

	for i := 0; i < len(rollAwardList); i++ {
		if id == rollAwardList[i].Id {
			return rollAwardList[i]
		}
	}

	return nil
}
func GetRollAwardItemIdList(id int) []int {
	raMutex.Lock()
	defer raMutex.Unlock()

	for i := 0; i < len(rollAwardList); i++ {
		if id == rollAwardList[i].Id {
			return rollAwardList[i].ItemIdList
		}
	}

	return nil
}
func GetRollAwardInfo() RollAwardInfoArray {
	raMutex.Lock()
	defer raMutex.Unlock()

	return rollAwardList
}
