package gredis

import (
	"bwallet/pkg/setting"
	"encoding/json"
	"github.com/gomodule/redigo/redis"
	"time"
)

var RedisConn *redis.Pool

func Setup() error {
	RedisConn = &redis.Pool{
		MaxIdle:     setting.RedisSetting.MaxIdle,
		MaxActive:   setting.RedisSetting.MaxActive,
		IdleTimeout: setting.RedisSetting.IdleTimeout,
		Dial: func() (redis.Conn, error) {
			c, err := redis.Dial("tcp", setting.RedisSetting.Host)
			if err != nil {
				return nil, err
			}
			if setting.RedisSetting.Password != "" {
				if _, err := c.Do("AUTH", setting.RedisSetting.Password); err != nil {
					c.Close()
					return nil, err
				}
			}
			return c, err
		},
		TestOnBorrow: func(c redis.Conn, t time.Time) error {
			_, err := c.Do("PING")
			return err
		},
	}

	return nil
}

//设置指定 key 的值
func Set(key string, data interface{}, time int, db int) error {
	conn := RedisConn.Get()
	defer conn.Close()

	value, err := json.Marshal(data)
	if err != nil {
		return err
	}

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return err
	}

	_, err = conn.Do("SET", key, value)
	if err != nil {
		return err
	}

	_, err = conn.Do("EXPIRE", key, time)
	if err != nil {
		return err
	}

	return nil
}

//获取指定 key 的值
func Get(key string, db int) ([]byte, error) {
	conn := RedisConn.Get()
	defer conn.Close()

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return nil, err
	}

	reply, err := redis.Bytes(conn.Do("GET", key))
	if err != nil {
		return nil, err
	}

	return reply, nil
}

func Exists(key string, db int) bool {
	conn := RedisConn.Get()
	defer conn.Close()

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return false
	}

	exists, err := redis.Bool(conn.Do("EXISTS", key))
	if err != nil {
		return false
	}

	return exists
}

//向有序集合添加一个或多个成员，或者更新已存在成员的分数
func ZAdd(key string, score int, data interface{}, db int) error {
	conn := RedisConn.Get()
	defer conn.Close()

	value, err := json.Marshal(data)
	if err != nil {
		return err
	}

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return err
	}

	_, err = conn.Do("ZADD", key, score, value)
	if err != nil {
		return err
	}

	return nil
}

func HashSet(key, field string, data interface{}, db int) error {
	conn := RedisConn.Get()
	defer conn.Close()

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return err
	}

	_, err := conn.Do("HSet", key, field, data)
	if err != nil {
		return err
	}

	return nil
}

func HashGet(key, field string, db int) ([]byte, error) {
	conn := RedisConn.Get()
	defer conn.Close()

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return nil, err
	}

	val, err := redis.Bytes(conn.Do("hget", key, field))
	if err != nil {
		return nil, err
	}

	return val, nil

}

//通过索引区间返回有序集合指定区间内的成员
func ZRange(key string, start, stop int, db int) ([]string, error) {
	conn := RedisConn.Get()
	defer conn.Close()

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return nil, err
	}

	rep, err := redis.Strings(conn.Do("ZRANGE", key, start, stop))
	if err != nil {
		return nil, err
	}

	return rep, nil
}

func Delete(key string, db int) (bool, error) {
	conn := RedisConn.Get()
	defer conn.Close()

	if _, err := conn.Do("SELECT", db); err != nil {
		conn.Close()
		return false, err
	}

	return redis.Bool(conn.Do("DEL", key))
}
