package session

import (
	"errors"
	"gogs.qqck.cn/s/gotools/randex"
	"sync"
	"time"
)

var err_nil = errors.New("session 无效")

type Sessiong struct {
	//并发锁
	lock sync.Mutex

	//哈希表
	hash map[string]*item

	time_life int64 // session有效时长，单位：秒
}

type item struct {
	time int64 // 最后访问时间，单位：秒
	val  any
}

func New() (t *Sessiong) {
	t = new(Sessiong)
	t.hash = make(map[string]*item)
	t.time_life = 60 * 60 * 24
	return
}

// SetTimeLife 设置session过期时间，默认为：24h
// life session有效时长，单位：秒
func (t *Sessiong) SetTimeLife(life int64) *Sessiong {
	if life < 1 {
		life = 60 * 60 * 24
	}
	t.lock.Lock()
	defer t.lock.Unlock()
	t.time_life = life
	return t
}

//-----------------------------------------------------------------------------------------------------API

func (t *Sessiong) Create(val any) (session string) {
	t.lock.Lock()
	defer t.lock.Unlock()
	for {
		session = randex.Str0aZ(64)
		if _, j_is := t.hash[session]; !j_is {
			break
		}
	}
	t.hash[session] = &item{
		time: time.Now().Unix(),
		val:  val,
	}
	return
}

func (t *Sessiong) Set(session string, val any) *Sessiong {
	t.lock.Lock()
	defer t.lock.Unlock()
	if _, j_is := t.hash[session]; !j_is {
		return t
	}
	t.hash[session].time = time.Now().Unix()
	t.hash[session].val = val
	return t
}

func (t *Sessiong) Get(session string) (any, error) {
	t.lock.Lock()
	defer t.lock.Unlock()
	if _, j_is := t.hash[session]; !j_is {
		return nil, err_nil
	}
	j_time := time.Now().Unix()
	if j_time-t.hash[session].time > t.time_life {
		delete(t.hash, session)
		return nil, err_nil
	}
	t.hash[session].time = j_time
	return t.hash[session].val, nil
}

// Delete 删除指定键
func (t *Sessiong) Delete(session string) {
	t.lock.Lock()
	defer t.lock.Unlock()
	delete(t.hash, session)
}

// Clean 清除过期的session
func (t *Sessiong) Clean() {
	t.lock.Lock()
	defer t.lock.Unlock()
	j_time := time.Now().Unix()
	for j_session, j_item := range t.hash {
		if j_time-j_item.time > t.time_life {
			delete(t.hash, j_session)
		}
	}
}
