package cache

import (
	. "code.hoteas.com/golang/hotime"
	"github.com/garyburd/redigo/redis"
	"strings"
	"time"
)

type CacheRedis struct {
	Host string
	Pwd  string
	Time int64
	conn redis.Conn
	tag  int64
	Error
}

//唯一标志
func (this *CacheRedis) GetTag() int64 {

	if this.tag == int64(0) {
		this.tag = time.Now().UnixNano()
	}
	return this.tag
}

func (this *CacheRedis) reCon() bool {
	var err error
	this.conn, err = redis.Dial("tcp", this.Host)
	if err != nil {
		this.conn = nil
		this.Error.SetError(err)
		return false
	}

	_, err = this.conn.Do("AUTH", this.Pwd)
	if err != nil {
		this.conn = nil
		this.Error.SetError(err)
		return false
	}
	return true
}
func (this *CacheRedis) del(key string) {
	del := strings.Index(key, "*")
	if del != -1 {
		val, err := redis.Strings(this.conn.Do("KEYS", key))
		if err != nil {
			return
		}
		this.conn.Send("MULTI")
		for i, _ := range val {
			this.conn.Send("DEL", val[i])
		}
		this.conn.Do("EXEC")
	} else {
		_, err := this.conn.Do("DEL", key)
		if err != nil {
			this.Error.SetError(err)
			_, err = this.conn.Do("PING")
			if err != nil {
				if this.reCon() {
					_, err = this.conn.Do("DEL", key)
				}
			}
		}
	}
}

//key value ,时间为时间戳
func (this *CacheRedis) set(key string, value string, time int64) {
	_, err := this.conn.Do("SET", key, value, "EX", ObjToStr(time))
	if err != nil {

		this.Error.SetError(err)
		_, err = this.conn.Do("PING")
		if err != nil {
			if this.reCon() {
				_, err = this.conn.Do("SET", key, value, "EX", ObjToStr(time))
			}
		}
	}
}

func (this *CacheRedis) get(key string) *Obj {
	reData := &Obj{}
	var err error
	reData.Data, err = redis.String(this.conn.Do("GET", key))
	if err != nil {
		reData.Data = nil
		if !strings.Contains(err.Error(), "nil returned") {
			this.Error.SetError(err)
			_, err = this.conn.Do("PING")
			if err != nil {
				if this.reCon() {
					reData.Data, err = redis.String(this.conn.Do("GET", key))
				}
			}

			return reData
		}
	}
	return reData
}

func (this *CacheRedis) Cache(key string, data ...interface{}) *Obj {
	reData := &Obj{}
	if this.conn == nil {
		re := this.reCon()
		if !re {
			return reData
		}
	}
	//查询缓存
	if len(data) == 0 {

		reData = this.get(key)
		return reData

	}
	tim := int64(0)
	//删除缓存
	if len(data) == 1 && data[0] == nil {
		this.del(key)
		return reData
	}
	//添加缓存
	if len(data) == 1 {

		if this.Time == 0 {
			this.Time = Config.GetInt64("cacheShortTime")
		}

		tim += this.Time
	}
	if len(data) == 2 {
		this.Error.SetError(nil)
		tempt := ObjToInt64(data[1], &this.Error)
		if tempt > tim {

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

			tim = tim + tempt
		}
	}

	this.set(key, ObjToStr(data[0]), tim)

	return reData

}
