package mod

import (
	"sync"
	"time"
)

/// 用户 token 保存在 redis hash 里， 处理 token 过期，设置 token 为 "1"

/// 1， 对于 login verify 通过的 guid, 按照返回的 expire 设置过期
/// 2, 对于使用 token 登录用户，且不再过期列表的 guid, 按照 4 小时过期

// 过期参数
type tokenExpireItem struct {
	expiresAt int64 //	过期时间点
}

type chanParam struct {
	guid  uint64
	param *tokenExpireItem
}

type TokenExpires struct {
	group map[uint64]*tokenExpireItem
	sync.Mutex
	chP      chan *chanParam
	isStoped int
}

func NewTokenExpires(chQuit chan struct{}) *TokenExpires {
	te := &TokenExpires{
		group: make(map[uint64]*tokenExpireItem),
		chP:   make(chan *chanParam, 1024),
	}

	go te.worker(chQuit)

	return te
}

//  让 guid 参与过期处理，此处应该在登录成功以后
//@expire 过期时长
func (self *TokenExpires) Put(guid uint64, expire int64) {
	if self.isStoped != 0 {
		return
	}

	go func() {
		expiresAt := time.Now().Unix() + expire
		select {
		case self.chP <- &chanParam{
			guid: guid,
			param: &tokenExpireItem{
				expiresAt: expiresAt,
			},
		}:
		case <-time.After(1 * time.Second):
		}
	}()
}

func (self *TokenExpires) worker(chQuit chan struct{}) {
	tk := time.NewTicker(1 * time.Minute)
	for {
		select {
		case p, ok := <-self.chP:
			if ok {
				if _, ok := self.group[p.guid]; !ok {
					self.Lock()
					self.group[p.guid] = p.param
					self.Unlock()
				}
			}
		case <-tk.C:
			now := time.Now().Unix()
			for guid, param := range self.group {
				if now >= param.expiresAt {
					_ = UpdateUserAttr(guid, "token", "1")

					self.Lock()
					delete(self.group, guid)
					self.Unlock()
				}
			}

		case <-chQuit:
			tk.Stop()
			close(self.chP)
			self.isStoped = 64
			return
		}
	}
}
