package mail

import (
	"strconv"
	"common/logger"
	"common/beegomap"
	"World/resume"
	"encoding/json"
	"time"
	"sort"
	"World/pb"
)

//todo..
//系统邮件存储格式给hashmap	key为SYS_MAIL_KEY field为mailid value为json格式的邮件内容
//个人邮件存储格式为hashmap key为PERSON_MAIL_KEY field为uid+mailid value为json格式的邮件内容

var (
	//m_userMailMap		*beegomap.BeeMap // = make(map[int32]*MailInfo) int32为MailID			//个人邮件列表
	m_SysMailMap		*beegomap.BeeMap // = make(map[int32]*MailInfo)			//系统邮件列表
)

const MAX_MAIL_NUM = 99									//最大邮件数量
const PERSON_MAIL_KEY = "PersonMailMap"				//玩家个人邮件集合
const SYS_MAIL_KEY = "SysMailMap"						//系统邮件集合
const USER_FETCH_SYS_MAILTIME_KEY = "UserFetchSysMailMap"		//玩家领取系统邮件时间戳

type Mails []*pb.MailInfo

func (c Mails) Len() int {
	return len(c)
}

func (c Mails) Less(i, j int) bool {
	if c[i].MailExpiredtime > c[j].MailExpiredtime {
		return true
	} else if c[i].MailExpiredtime < c[j].MailExpiredtime {
		return false
	} else {
		return c[i].MailId < c[j].MailId
	}
}

func (c Mails) Swap(i, j int) {
	tmp := c[i]
	c[i] = c[j]
	c[j] = tmp
}
/*
//结构暂定 等待道具结构具体定义以后可以修改
type AttInfo struct {
	ItemId 		uint32		//物品ID
	ItemNum		uint32		//物品数量
}

type MailInfo struct {
	MailID		uint32		//邮件ID
	MailType	int32		//邮件类型 0系统 1个人
	MailState	int32		//是否已经领取 0未1已经领取
	Title		string		//邮件标题
	SenderID	uint32		//发送者ID 系统为0
	Appellation	string		//开头
	Content		string		//内容
	Inscribe	string		//签名
	Sendtime	uint32		//发送时间
	ExpiredTime	uint32		//过期时间
	Attachement	[]AttInfo		//附件
}*/

func MyTest() {
	var sysmailinfo pb.MailInfo
	var minfos []*pb.MailInfo

	sysmailinfo.MailTitle = "what thefuck"
	sysmailinfo.MailSendtime = uint32(time.Now().Unix())
	sysmailinfo.MailSenderId = 0
	sysmailinfo.MailType = 0
	sysmailinfo.MailState = 0
	sysmailinfo.MailId = 3
	sysmailinfo.MailInscribe = "you idot"
	sysmailinfo.MailExpiredtime = uint32(time.Now().Unix() + 3600*24*30)
	sysmailinfo.MailContent = "i am stupid"
	sysmailinfo.AttachmentList = nil
	sysmailinfo.MailAppelaction = "hahahaha"

	minfo := new(pb.MailInfo)
	minfo.MailTitle = "什么情况"
	minfo.MailSendtime = uint32(time.Now().Unix())
	minfo.MailSenderId = 0
	minfo.MailType = 0
	minfo.MailState = 0
	minfo.MailId = 1
	minfo.MailInscribe = "你这个傻逼"
	minfo.MailExpiredtime = uint32(time.Now().Unix() + 3600*24*20)
	minfo.MailContent = "我是一封傻逼傻鸟巨大的傻逼邮件"
	minfo.AttachmentList = nil
	minfo.MailAppelaction = "哈哈哈哈"

	minfo1 := new(pb.MailInfo)
	minfo1.MailTitle = "what thefuck"
	minfo1.MailSendtime = uint32(time.Now().Unix())
	minfo1.MailSenderId = 0
	minfo1.MailType = 0
	minfo1.MailState = 0
	minfo1.MailId = 2
	minfo1.MailInscribe = "you idot"
	minfo1.MailExpiredtime = uint32(time.Now().Unix() + 3600*24*10)
	minfo1.MailContent = "i am stupid"
	minfo1.AttachmentList = nil
	minfo1.MailAppelaction = "hahahaha"

	minfos = append(minfos,minfo)
	minfos = append(minfos,minfo1)
	cur := uint32(time.Now().Unix())
	cli := resume.GetRedisClient()
	sMailInfos, _ := json.Marshal(sysmailinfo)
	spMailInfos, _ := json.Marshal(minfos)
	cli.HSet(SYS_MAIL_KEY,strconv.Itoa(int(sysmailinfo.MailId)),string(sMailInfos))
	cli.HSet(PERSON_MAIL_KEY,strconv.Itoa(12355),string(spMailInfos))
	cli.HSet(PERSON_MAIL_KEY,strconv.Itoa(12365),string(spMailInfos))
	cli.HSet(USER_FETCH_SYS_MAILTIME_KEY,strconv.Itoa(12355),strconv.Itoa(int(cur)))

	logger.Info("MAILMyTest")
}

//初始化
func InitMail() error {
	m_SysMailMap = beegomap.NewBeeMap()

	//临时测试
	MyTest()

	err := LoadSysMail()
	if err != nil {
		logger.Notic("InitMail failed err:%v",err)
		return err
	}
	return nil
}

//加载系统邮件
func LoadSysMail() error {
	logger.Info("LoadSysMail!")
	cli := resume.GetRedisClient()
	v, err := cli.HMGets(SYS_MAIL_KEY)
	if err != nil {
		logger.Warn("redis get Map_ClubGame failed")
		return err
	}else {
		for i := 0; i < len(v); i += 2 {
			//k := v[i].([]byte)
			val := v[i+1].([]byte)

			var mailInfo pb.MailInfo
			err := json.Unmarshal([]byte(val), &mailInfo)
			if err != nil {
				logger.Warn("LoadSysMail Unmarshal failed err:%v", err)
				break
			}

			pMailInfo := new(pb.MailInfo)
			pMailInfo.MailAppelaction = mailInfo.MailAppelaction
			pMailInfo.AttachmentList = append(pMailInfo.AttachmentList,mailInfo.AttachmentList...)
			pMailInfo.MailContent = mailInfo.MailContent
			pMailInfo.MailExpiredtime = mailInfo.MailExpiredtime
			pMailInfo.MailInscribe = mailInfo.MailInscribe
			pMailInfo.MailId = mailInfo.MailId
			pMailInfo.MailState = mailInfo.MailState
			pMailInfo.MailType = mailInfo.MailType
			pMailInfo.MailSenderId = mailInfo.MailSenderId
			pMailInfo.MailSendtime = mailInfo.MailSendtime
			pMailInfo.MailTitle = mailInfo.MailTitle
			pMailInfo.Isexpired = mailInfo.Isexpired
			m_SysMailMap.Set(mailInfo.MailId,pMailInfo)

			logger.Info("LoadSysMail mailed %v mailinfo:%v", mailInfo.MailId,mailInfo)
		}
	}
	return nil
}



//保存系统邮件
func SaveOneSysMail(mailid uint32,mailinfo *pb.MailInfo) error {
	cli := resume.GetRedisClient()
	var s_mailinfo pb.MailInfo
	s_mailinfo = *mailinfo
	sMailInfos, _ := json.Marshal(s_mailinfo)
	err := cli.HSet(SYS_MAIL_KEY,strconv.Itoa(int(mailid)),string(sMailInfos))
	if err != nil {
		logger.Notic("SaveOneSysMail failed err:%v",err)
		return err
	}

	logger.Info("SaveOneSysMail success mailid:%v mailinfo:%v",mailid,s_mailinfo)
	return nil
}

//处理玩家邮件 删除多余的
func HandleAndGetUserMail(uid uint32,lasttime uint32) (Mails,error) {
	var finalList Mails
	mailFromUserRedis,err := LoadUserMail(uid)
	if err != nil {
		logger.Notic("LoadUserMail failed uid:%v err:%v",uid,err)
		return nil,err
	}

	finalList = append(finalList,mailFromUserRedis...)

	//将系统邮件中未读取的取出发出
	for _, vv := range m_SysMailMap.Items() {
		valMailInfos, _ := vv.(*pb.MailInfo)
		if valMailInfos.MailSendtime > lasttime {
			finalList = append(finalList,valMailInfos)
		}
	}

	//排序
	sort.Sort(finalList)

	if len(finalList) > MAX_MAIL_NUM {
		finalList = finalList[0:MAX_MAIL_NUM]
	}

	logger.Info("HandleAndGetUserMail finalList:%v",finalList)
	return finalList,nil
}

//加载玩家邮件
func LoadUserMail(uid uint32) (Mails,error) {
	logger.Info("LoadUserMail!")
	var mails Mails
	cli := resume.GetRedisClient()
	v, err := cli.HGet(PERSON_MAIL_KEY,strconv.Itoa(int(uid)))
	if err != nil {
		logger.Warn("redis get LoadUserMail failed err:%v",err)
		return nil,err
	}else {
		err = json.Unmarshal([]byte(v), &mails)
		logger.Info("LoadUserMail v:%v", v)
		logger.Info("LoadUserMail mailinfo:%v", mails)
	}

	return mails,nil
}

//保存玩家邮件
func SaveUserMail(mails Mails,uid uint32) error {
	logger.Info("SaveUserMail!")
	cli := resume.GetRedisClient()
	sMailInfos, _ := json.Marshal(mails)
	err := cli.HSet(PERSON_MAIL_KEY,strconv.Itoa(int(uid)),string(sMailInfos))
	if err != nil {
		logger.Warn("redis SaveUserMail failed err:%v",err)
		return err
	}

	return nil
}

//加载玩家最后一次读取系统邮件时间
func LoadUserFetchSysMailTime(uid uint32) (uint32,error){
	cli := resume.GetRedisClient()
	last_time,err := cli.HGet(USER_FETCH_SYS_MAILTIME_KEY,strconv.Itoa(int(uid)))
	if err != nil {
		logger.Notic("LoadUserFetchSysMailTime failed err:%v",err)
		return 0,err
	}

	n_last_time,_ := strconv.Atoi(last_time)
	return uint32(n_last_time),nil
}

//保存玩家最后一次读取系统邮件时间
func SaveUserFetchSysMailTime(uid uint32,last_time uint32) error {
	cli := resume.GetRedisClient()
	err := cli.HSet(USER_FETCH_SYS_MAILTIME_KEY,strconv.Itoa(int(uid)),string(last_time))
	if err != nil {
		logger.Notic("SaveUserFetchSysMailTime failed err:%v",err)
		return err
	}

	logger.Info("SaveUserFetchSysMailTime success uid:%v last_time:%v",uid,last_time)
	return nil
}

func ModifyMailInfo(uid uint32,mail_id uint32) (*pb.MailInfo,error){
	var mailList Mails
	var err error
	var mailinfo *pb.MailInfo
	if mailList, err = HandleAndGetUserMail(uid, uint32(time.Now().Unix())); err != nil {
		logger.Notic("player uid:%v mail.ModifyMailInfo:%v ", uid, err)
		return nil,nil
	}

	for _,mails := range mailList {
		if mails.MailId != mail_id {
			continue
		}

		mails.MailState = 1

		mailinfo = new(pb.MailInfo)
		mailinfo.MailId = mails.MailId
		mailinfo.MailState = mails.MailState
		mailinfo.Isexpired = mails.Isexpired
		mailinfo.MailAppelaction = mails.MailAppelaction
		mailinfo.MailContent = mails.MailContent
		mailinfo.MailExpiredtime = mails.MailExpiredtime
		mailinfo.MailInscribe = mails.MailInscribe
		mailinfo.MailSenderId = mails.MailSenderId
		mailinfo.MailTitle = mails.MailTitle
		mailinfo.MailType = mails.MailType
		mailinfo.AttachmentList = append(mailinfo.AttachmentList,mails.AttachmentList...)
		mailinfo.MailSendtime = mails.MailId
		break
	}

	SaveUserMail(mailList,uid)
	return mailinfo,nil
}


//add a line of comment