package cache

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

type CacheRedis struct {
	TimeOut    int64
	DbSet      bool
	SessionSet bool
	Host       string
	Pwd        string
	Port       int64
	conn       redis.Conn
	tag        int64
	ContextBase
	*Error
}

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

	return that.Error

}

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

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

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

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

	if that.Pwd != "" {
		_, err = that.conn.Do("AUTH", that.Pwd)
		if err != nil {
			that.conn = nil
			that.Error.SetError(err)
			return false
		}
	}

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

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

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

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

			return reData
		}
	}
	return reData
}

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

		reData = that.get(key)
		return reData

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

		if that.TimeOut == 0 {
			//that.Time = Config.GetInt64("cacheShortTime")
		}

		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.GetError() == nil {

			tim = tim + tempt
		}
	}

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

	return reData

}
