package models

import (
	"errors"
	"github.com/astaxie/beego"
	"github.com/astaxie/beego/orm"
	"github.com/astaxie/beego/validation"
	"log"
	"sync"
	"time"
	"fmt"
)

type HotfixInfo struct {
	Id			int64
	Channel		int64 `valid:"Required"`					// 渠道
	Type		int64 `valid:"Required"`					// 平台 1-安卓 2-苹果
	Version		string `orm:"size(64)" valid:"Required"`	// 最新版本
	DowloadAddr	string `orm:"size(1024)"`					// 下载地址
	FileSize	string `orm:"size(64)"`						// 文件大小
	CreateTs	int64										// 创建时间
	ModifyTs	int64										// 修改时间
}

type HotfixInfoArray []*HotfixInfo

var hotfixInfo []*HotfixInfo
var hfMutex sync.Mutex

func init() {
	orm.RegisterModel(new(HotfixInfo))
}

func InitHotfixInfo() {
	var hfs []*HotfixInfo
	o := orm.NewOrm()
	o.Raw("SELECT * from tb_hotfix_info").QueryRows(&hfs)

	for i := 0; i < len(hfs); i++ {
		hotfixInfo = append(hotfixInfo, hfs[i])
	}
	beego.Info("load hotfix info", len(hotfixInfo))
}

func (hf *HotfixInfo) TableName() string {
	return "tb_hotfix_info"
}

func checkHotfixInfo(hf *HotfixInfo) (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 AddHotfixInfo(hf *HotfixInfo) (int64, error) {
	if err := checkHotfixInfo(hf); err != nil {
		return 0, err
	}

	hf.CreateTs = time.Now().Unix()
	hf.ModifyTs = hf.CreateTs

	o := orm.NewOrm()
	id, err := o.Insert(hf)

	if err == nil {
		hfMutex.Lock()
		hotfixInfo = append(hotfixInfo, hf)
		hfMutex.Unlock()
	}

	return id, err
}

func UpdateHotfixInfo(hf *HotfixInfo) (int64, error) {
	if err := checkHotfixInfo(hf); err != nil {
		log.Println("UpdateHotfixInfo err:", err)
		return 0, err
	}
	now := time.Now().Unix()
	o := orm.NewOrm()
	param := make(orm.Params)

	param["Channel"] = hf.Channel
	param["Version"] = hf.Version
	param["DowloadAddr"] = hf.DowloadAddr
	param["FileSize"] = hf.FileSize
	param["ModifyTs"] = now

	var table HotfixInfo
	num, err := o.QueryTable(table).Filter("Id", hf.Id).Update(param)
	log.Println(fmt.Sprintf("UpdateHotfixInfo id[%d] num[%d] err:%v", hf.Id, num, err))

	if err == nil {
		hfMutex.Lock()
		for i := 0; i < len(hotfixInfo); i++ {
			if hf.Id == hotfixInfo[i].Id {
				old := hotfixInfo[i]

				old.Channel = hf.Channel
				old.Version = hf.Version
				old.DowloadAddr = hf.DowloadAddr
				old.FileSize = hf.FileSize
				old.ModifyTs = now

				break
			}
		}

		hfMutex.Unlock()
	}
	return num, err
}

func DelHotfixInfoById(Id int64) (int64, error) {
	hfMutex.Lock()
	defer hfMutex.Unlock()

	o := orm.NewOrm()
	status, err := o.Delete(&HotfixInfo{Id: Id})

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

	return status, err
}

func GetHotfixInfoById(id int64) (hf *HotfixInfo) {
	hfMutex.Lock()
	defer hfMutex.Unlock()

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

	return nil
}
func GetHotfixInfoByChannel(channel int64) (hf *HotfixInfo) {
	hfMutex.Lock()
	defer hfMutex.Unlock()

	for i := 0; i < len(hotfixInfo); i++ {
		if channel == hotfixInfo[i].Channel {
			return hotfixInfo[i]
		}
	}

	return nil
}

func GetHotfixInfo() HotfixInfoArray {
	hfMutex.Lock()
	defer hfMutex.Unlock()

	return hotfixInfo
}
