package main

import (
	"crypto/md5"
	"fmt"
	"math/rand"
	"time"

	"redisdog/model"
)

type Session struct {
	Sess    string             `json:"sess"`
	Expire  int64              `json:"expire"`
	Account *model.AccountsRow `json:"account"`
}

type SessionPoll struct {
	poll map[string]*Session
	lock chan int
	ttl  int64
}

func NewSessionPoll(ttl int64) *SessionPoll {
	p := &SessionPoll{
		poll: make(map[string]*Session, 1024),
		lock: make(chan int, 1),
		ttl:  ttl,
	}
	go p.timer()
	return p
}

func (p *SessionPoll) timer() {
	for {
		time.Sleep(time.Minute * 1)
		ts := time.Now().Unix()
		expired := make([]string, len(p.poll))
		cnt := 0
		p.lock <- 1
		for id, s := range p.poll {
			if s.Expire <= ts {
				expired[cnt] = id
				cnt++
			}
		}
		for _, id := range expired {
			delete(p.poll, id)
		}
		<-p.lock
	}
}

func (p *SessionPoll) Get(sessid string) (*Session, bool) {
	p.lock <- 1
	s, ok := p.poll[sessid]
	if ok {
		p.poll[sessid].Expire = time.Now().Unix() + p.ttl
	}
	<-p.lock
	return s, ok
}

func (p *SessionPoll) Set(sessid string, sess *Session) {
	if sess.Expire == 0 {
		sess.Expire = time.Now().Unix() + p.ttl
	}
	p.lock <- 1
	p.poll[sessid] = sess
	<-p.lock
}

func (p *SessionPoll) Del(sessid string) {
	p.lock <- 1
	delete(p.poll, sessid)
	<-p.lock
}

func makeSessionId(cliAddr string) string {
	return fmt.Sprintf("%x", md5.Sum([]byte(fmt.Sprintf("sess|%s|%d|d", cliAddr, time.Now().Unix(), rand.Int63()))))
}
