package cache

import (
	. "code.hoteas.com/golang/hotime/common"
	"errors"
)

// HoTimeCache 可配置memory，db，redis，默认启用memory，默认优先级为memory>redis>db,memory与数据库缓存设置项一致，
//缓存数据填充会自动反方向反哺，加入memory缓存过期将自动从redis更新，但memory永远不会更新redis，如果是集群建议不要开启memory，配置即启用
type HoTimeCache struct {
	*Error
	dbCache     *CacheDb
	redisCache  *CacheRedis
	memoryCache *CacheMemory
	Config      Map
}

func (that *HoTimeCache) Session(key string, data ...interface{}) *Obj {
	var reData *Obj
	if len(data) == 0 {
		//内存缓存有
		if that.memoryCache != nil && that.memoryCache.SessionSet {
			reData = that.memoryCache.Cache(key, data...)
			if reData.Data != nil {
				return reData
			}
		}

		//redis缓存有
		if that.redisCache != nil && that.redisCache.SessionSet {
			reData = that.redisCache.Cache(key, data...)
			if reData.Data != nil {
				if that.memoryCache != nil && that.memoryCache.SessionSet {
					that.memoryCache.Cache(key, reData.Data)
				}
				return reData
			}
		}

		//db缓存有
		if that.dbCache != nil && that.dbCache.SessionSet {
			reData = that.dbCache.Cache(key, data...)
			if reData.Data != nil {
				if that.memoryCache != nil && that.memoryCache.SessionSet {
					that.memoryCache.Cache(key, reData.Data)
				}
				if that.redisCache != nil && that.redisCache.SessionSet {
					that.redisCache.Cache(key, reData.Data)
				}

				return reData
			}
		}
		return reData
	}

	//设置缓存
	//设置内存缓存
	if that.memoryCache != nil && that.memoryCache.SessionSet {
		reData = that.memoryCache.Cache(key, data...)
	}
	//redis缓存有
	if that.redisCache != nil && that.redisCache.SessionSet {
		reData = that.redisCache.Cache(key, data...)
	}
	//redis缓存有
	if that.dbCache != nil && that.dbCache.SessionSet {
		reData = that.dbCache.Cache(key, data...)
	}
	return reData

}
func (that *HoTimeCache) Db(key string, data ...interface{}) *Obj {
	var reData *Obj
	if len(data) == 0 {
		//内存缓存有
		if that.memoryCache != nil && that.memoryCache.DbSet {
			reData = that.memoryCache.Cache(key, data...)
			if reData.Data != nil {
				return reData
			}
		}

		//redis缓存有
		if that.redisCache != nil && that.redisCache.DbSet {
			reData = that.redisCache.Cache(key, data...)
			if reData.Data != nil {
				if that.memoryCache != nil && that.memoryCache.DbSet {
					that.memoryCache.Cache(key, reData.Data)
				}
				return reData
			}
		}

		//redis缓存有
		if that.dbCache != nil && that.dbCache.DbSet {
			reData = that.dbCache.Cache(key, data...)
			if reData.Data != nil {
				if that.memoryCache != nil && that.memoryCache.DbSet {
					that.memoryCache.Cache(key, reData.Data)
				}

				if that.redisCache != nil && that.redisCache.DbSet {
					that.redisCache.Cache(key, reData.Data)
				}

				return reData
			}
		}
		return reData
	}

	//设置缓存
	//设置内存缓存
	if that.memoryCache != nil && that.memoryCache.DbSet {
		reData = that.memoryCache.Cache(key, data...)
	}
	//redis缓存有
	if that.redisCache != nil && that.redisCache.DbSet {
		reData = that.redisCache.Cache(key, data...)
	}
	//redis缓存有
	if that.dbCache != nil && that.dbCache.DbSet {
		reData = that.dbCache.Cache(key, data...)
	}
	return reData
}

func (that *HoTimeCache) Cache(key string, data ...interface{}) *Obj {
	var reData *Obj
	if len(data) == 0 {
		//内存缓存有
		if that.memoryCache != nil {
			reData = that.memoryCache.Cache(key, data...)
			if reData != nil {
				return reData
			}
		}

		//redis缓存有
		if that.redisCache != nil {
			reData = that.redisCache.Cache(key, data...)
			if reData.Data != nil {

				if that.memoryCache != nil {
					that.memoryCache.Cache(key, reData.Data)
				}
				return reData
			}
		}

		//redis缓存有
		if that.dbCache != nil {
			reData = that.dbCache.Cache(key, data...)
			if reData.Data != nil {
				if that.memoryCache != nil {
					that.memoryCache.Cache(key, reData.Data)
				}
				if that.redisCache != nil {
					that.redisCache.Cache(key, reData.Data)
				}
				return reData
			}
		}
		return reData
	}

	//设置缓存
	//设置内存缓存
	if that.memoryCache != nil {
		reData = that.memoryCache.Cache(key, data...)
	}
	//redis缓存有
	if that.redisCache != nil {
		reData = that.redisCache.Cache(key, data...)
	}
	//redis缓存有
	if that.dbCache != nil {
		reData = that.dbCache.Cache(key, data...)
	}
	return reData
}

func (that *HoTimeCache) Init(config Map, hotimeDb HoTimeDBInterface, err ...*Error) {
	//防止空数据问题
	if config == nil {
		config = Map{}
	}
	if err[0] != nil {
		that.Error = err[0]
	}
	that.Config = config
	//memory配置初始化
	memory := that.Config.GetMap("memory")
	if memory == nil {
		memory = Map{
			"db":      true,
			"session": true,
			"sort":    0,
			"timeout": 60 * 60 * 2,
		}

	}
	if memory.Get("db") == nil {
		memory["db"] = true
	}

	if memory.Get("session") == nil {
		memory["session"] = true
	}

	if memory.Get("timeout") == nil {
		memory["timeout"] = 60 * 60 * 2
	}
	that.Config["memory"] = memory
	that.memoryCache = &CacheMemory{TimeOut: memory.GetCeilInt64("timeout"),
		DbSet: memory.GetBool("db"), SessionSet: memory.GetBool("session")}
	if err[0] != nil {
		that.memoryCache.SetError(err[0])
	}

	//db配置初始化
	redis := that.Config.GetMap("redis")
	if redis != nil {
		if redis.GetString("host") == "" || redis.GetString("port") == "" {
			if err[0] != nil {
				err[0].SetError(errors.New("请检查redis配置host和port配置"))
			}
			return
		}
		if redis.Get("db") == nil {
			redis["db"] = true
		}

		if redis.Get("session") == nil {
			redis["session"] = true
		}

		if redis.Get("timeout") == nil {
			redis["timeout"] = 60 * 60 * 24 * 15
		}
		that.Config["redis"] = redis
		that.redisCache = &CacheRedis{TimeOut: redis.GetCeilInt64("timeout"),
			DbSet: redis.GetBool("db"), SessionSet: redis.GetBool("session"), Host: redis.GetString("host"),
			Pwd: redis.GetString("password"), Port: redis.GetCeilInt64("port")}

		if err[0] != nil {
			that.redisCache.SetError(err[0])
		}
	}

	//db配置初始化
	db := that.Config.GetMap("db")
	if db != nil {

		if db.Get("db") == nil {
			db["db"] = false
		}

		if db.Get("session") == nil {
			db["session"] = true
		}
		if db.Get("timeout") == nil {
			db["timeout"] = 60 * 60 * 24 * 30
		}
		that.Config["db"] = db

		that.dbCache = &CacheDb{TimeOut: db.GetCeilInt64("timeout"),
			DbSet: db.GetBool("db"), SessionSet: db.GetBool("session"),
			Db: hotimeDb}

		if err[0] != nil {
			that.dbCache.SetError(err[0])
		}
	}

}
