package cache

import (
	. "code.hoteas.com/golang/hotime/common"
	"strings"
	"sync"
	"time"
)

type CacheMemory struct {
	TimeOut    int64
	DbSet      bool
	SessionSet bool
	Map
	*Error
	ContextBase
	mutex *sync.RWMutex
}

func (that *CacheMemory) GetError() *Error {

	return that.Error

}

func (that *CacheMemory) SetError(err *Error) {
	that.Error = err
}

//获取Cache键只能为string类型
func (that *CacheMemory) get(key string) interface{} {
	that.Error.SetError(nil)
	if that.Map == nil {
		that.Map = Map{}
	}

	if that.Map[key] == nil {
		return nil
	}
	data := that.Map.Get(key, that.Error).(cacheData)
	if that.Error.GetError() != nil {
		return nil
	}

	if data.time < time.Now().Unix() {
		delete(that.Map, key)
		return nil
	}
	return data.data
}

func (that *CacheMemory) refreshMap() {

	go func() {
		that.mutex.Lock()
		defer that.mutex.Unlock()
		for key, v := range that.Map {
			data := v.(cacheData)
			if data.time <= time.Now().Unix() {
				delete(that.Map, key)
			}
		}

	}()

}

//key value ,时间为时间戳
func (that *CacheMemory) set(key string, value interface{}, time int64) {
	that.Error.SetError(nil)
	var data cacheData

	if that.Map == nil {
		that.Map = Map{}
	}

	dd := that.Map[key]

	if dd == nil {
		data = cacheData{}
	} else {
		data = dd.(cacheData)
	}

	data.time = time
	data.data = value

	that.Map.Put(key, data)
}

func (that *CacheMemory) delete(key string) {
	del := strings.Index(key, "*")
	//如果通配删除
	if del != -1 {
		key = Substr(key, 0, del)
		for k, _ := range that.Map {
			if strings.Index(k, key) != -1 {
				delete(that.Map, k)

			}
		}

	} else {
		delete(that.Map, key)
	}

}

func (that *CacheMemory) Cache(key string, data ...interface{}) *Obj {

	x := RandX(1, 100000)
	if x > 99950 {
		that.refreshMap()
	}
	if that.mutex == nil {
		that.mutex = &sync.RWMutex{}
	}

	reData := &Obj{Data: nil}

	if len(data) == 0 {
		that.mutex.RLock()
		reData.Data = that.get(key)
		that.mutex.RUnlock()
		return reData
	}
	tim := time.Now().Unix()

	if len(data) == 1 && data[0] == nil {
		that.mutex.Lock()
		that.delete(key)
		that.mutex.Unlock()
		return reData
	}

	if len(data) == 1 {

		tim = tim + that.TimeOut

	}
	if len(data) == 2 {
		that.Error.SetError(nil)
		tempt := ObjToInt64(data[1], that.Error)

		if tempt > tim {

			tim = tempt
		} else if that.Error.GetError() == nil {

			tim = tim + tempt
		}
	}
	that.mutex.Lock()
	that.set(key, data[0], tim)
	that.mutex.Unlock()
	return reData

}
