package models

// 兑换码
import (
	"box-gm/utils"
	"encoding/json"
	"errors"
	"fmt"
	"log"
	"sync"
	"time"

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

type ExchangeItemsInfo struct {
	ItemId int `json:"id"`     // 道具ID
	Count  int `json:"count"`  // 数量
	Weight int `json:"weight"` // 权重
}
type ExchangeCodeInfo struct {
	Pcode      string               `json:"pcode"`      // 兑换码
	AwardTimes int64                `json:"awardTimes"` // 领奖次数
	CreateTime int64                `json:"creatTime"`  // 创建时间
	ModifyTime int64                `json:"modifyTime"` // 修改时间
	ExpireTime int64                `json:"expireTime"` // 过期时间
	Items      []*ExchangeItemsInfo `json:"items"`      // 随机奖励列表

}

type ExchangeCodeInfoArray []*ExchangeCodeInfo

var exchangeCodeList ExchangeCodeInfoArray
var ecMutex sync.Mutex
var MAIN_KEY = "exchange:code"

// 兑换码key
func get_exchange_code_key(pcode string) string {
	return fmt.Sprintf("%s:%s", MAIN_KEY, pcode)
}

// 初始化兑换码
func InitExchangeCodeInfo() {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		fmt.Println("get redis pool fail")
		return
	}
	rd := pool.Get()
	defer rd.Close()

	result, _ := redis.Values(rd.Do("smembers", MAIN_KEY))
	for _, v := range result {
		pcode := string(v.([]byte))
		pKey := get_exchange_code_key(pcode)
		awardTimes, _ := redis.Int64(rd.Do("hget", pKey, "awardTimes"))
		creatTime, _ := redis.Int64(rd.Do("hget", pKey, "creatTime"))
		modifyTime, _ := redis.Int64(rd.Do("hget", pKey, "modifyTime"))
		expireTime, _ := redis.Int64(rd.Do("hget", pKey, "expireTime"))
		items, _ := redis.String(rd.Do("hget", pKey, "items"))

		var _items []*ExchangeItemsInfo
		json.Unmarshal([]byte(items), &_items)
		exchangeCodeList = append(exchangeCodeList, &ExchangeCodeInfo{
			Pcode:      pcode,
			AwardTimes: awardTimes,
			CreateTime: creatTime,
			ModifyTime: modifyTime,
			ExpireTime: expireTime,
			Items:      _items,
		})
	}

	beego.Info("load exchange code info", len(exchangeCodeList))
}

func checkExchangeCodeInfo(hf *ExchangeCodeInfo) (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
}

// 新增兑换码
func AddExchangeCodeInfo(hf *ExchangeCodeInfo) error {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		return fmt.Errorf("get redis pool fail")
	}
	rd := pool.Get()
	defer rd.Close()

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

	hf.CreateTime = time.Now().Unix()
	hf.ModifyTime = hf.CreateTime

	pKey := get_exchange_code_key(hf.Pcode)
	rd.Do("hset", pKey, "awardTimes", hf.AwardTimes)
	rd.Do("hset", pKey, "creatTime", hf.CreateTime)
	rd.Do("hset", pKey, "modifyTime", hf.ModifyTime)
	rd.Do("hset", pKey, "expireTime", hf.ExpireTime)
	items, _ := json.Marshal(hf.Items)
	rd.Do("hset", pKey, "items", items)
	rd.Do("sadd", MAIN_KEY, hf.Pcode)

	ecMutex.Lock()
	exchangeCodeList = append(exchangeCodeList, hf)
	ecMutex.Unlock()

	return nil
}

// 修改兑换码
func UpdateExchangeCodeInfo(hf *ExchangeCodeInfo) error {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		return fmt.Errorf("get redis pool fail")
	}
	rd := pool.Get()
	defer rd.Close()

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

	hf.ModifyTime = time.Now().Unix()

	pKey := get_exchange_code_key(hf.Pcode)
	rd.Do("hset", pKey, "awardTimes", hf.AwardTimes)
	rd.Do("hset", pKey, "modifyTime", hf.ModifyTime)
	rd.Do("hset", pKey, "expireTime", hf.ExpireTime)
	items, _ := json.Marshal(hf.Items)
	rd.Do("hset", pKey, "items", items)
	rd.Do("sadd", MAIN_KEY, hf.Pcode)

	ecMutex.Lock()
	for i := 0; i < len(exchangeCodeList); i++ {
		if hf.Pcode == exchangeCodeList[i].Pcode {
			old := exchangeCodeList[i]

			old.AwardTimes = hf.AwardTimes
			old.ModifyTime = hf.ModifyTime
			old.ExpireTime = hf.ExpireTime
			old.Items = hf.Items
			break
		}
	}
	ecMutex.Unlock()

	return nil

}

// 删除兑换码
func DelExchangeCodeInfoById(pcode string) error {
	pool := utils.GetAccountRedisPool()
	if pool == nil {
		return fmt.Errorf("get redis pool fail")
	}
	rd := pool.Get()
	defer rd.Close()

	ecMutex.Lock()
	defer ecMutex.Unlock()

	rd.Do("srem", MAIN_KEY, pcode)
	pKey := get_exchange_code_key(pcode)
	_, err := rd.Do("del", pKey)
	if err != nil {
		log.Println(err)
		return err
	}

	for i := 0; i < len(exchangeCodeList); i++ {
		if pcode == exchangeCodeList[i].Pcode {
			ii := i + 1
			exchangeCodeList = append(exchangeCodeList[:i], exchangeCodeList[ii:]...)
		}
	}

	return nil
}

// 获取兑换码信息
func GetExchangeCodeInfoByCode(pcode string) (hf *ExchangeCodeInfo) {
	ecMutex.Lock()
	defer ecMutex.Unlock()

	for i := 0; i < len(exchangeCodeList); i++ {
		if pcode == exchangeCodeList[i].Pcode {
			return exchangeCodeList[i]
		}
	}

	return nil
}
func GetExchangeCodeInfo() ExchangeCodeInfoArray {
	ecMutex.Lock()
	defer ecMutex.Unlock()

	return exchangeCodeList
}
