func ConnectTimeout() time.Duration {
	return connectTimeout
}
ConnectTimeout returns the current connect timeout for new connections
package simpleredis
import (
	"errors"
	"strconv"
	"strings"
	"time"
	"github.com/gomodule/redigo/redis"
)
const (
	Version = 2.6
	defaultRedisServer = ":6379"
)
type redisDatastructure struct {
	pool    *ConnectionPool
	id      string
	dbindex int
}
type (
	ConnectionPool redis.Pool
	List     redisDatastructure
	Set      redisDatastructure
	HashMap  redisDatastructure
	KeyValue redisDatastructure
)
var (
	connectTimeout = 7 * time.Second
	readTimeout    = 7 * time.Second
	writeTimeout   = 7 * time.Second
	idleTimeout    = 240 * time.Second
	maxIdleConnections = 3
)
func newRedisConnection() (redis.Conn, error) {
	return newRedisConnectionTo(defaultRedisServer)
}
func newRedisConnectionTo(hostColonPort string) (redis.Conn, error) {
	if _, theRest, ok := twoFields(hostColonPort, "@"); ok {
		hostColonPort = theRest
	}
	hostColonPort = strings.TrimSpace(hostColonPort)
	c, err := redis.Dial("tcp", hostColonPort, redis.DialConnectTimeout(connectTimeout), redis.DialReadTimeout(readTimeout), redis.DialWriteTimeout(writeTimeout))
	if err != nil {
		if c != nil {
			c.Close()
		}
		return nil, err
	}
	return c, nil
}
func getString(bi []interface{}, i int) string {
	return string(bi[i].([]uint8))
}
func TestConnection() (err error) {
	return TestConnectionHost(defaultRedisServer)
}
func TestConnectionHost(hostColonPort string) (err error) {
	conn, err := newRedisConnectionTo(hostColonPort)
	defer func() {
		if conn != nil {
			conn.Close()
		}
		if r := recover(); r != nil {
			err = errors.New("Could not connect to redis server: " + hostColonPort)
		}
	}()
	return err
}
func NewConnectionPool() *ConnectionPool {
	redisPool := &redis.Pool{
		MaxIdle:     maxIdleConnections,
		IdleTimeout: idleTimeout,
		Dial:        newRedisConnection,
	}
	pool := ConnectionPool(*redisPool)
	return &pool
}
func twoFields(s, delim string) (string, string, bool) {
	if strings.Count(s, delim) != 1 {
		return s, "", false
	}
	fields := strings.Split(s, delim)
	return fields[0], fields[1], true
}
func NewConnectionPoolHost(hostColonPort string) *ConnectionPool {
	redisPool := &redis.Pool{
		MaxIdle:     maxIdleConnections,
		IdleTimeout: idleTimeout,
		Dial: func() (redis.Conn, error) {
			conn, err := newRedisConnectionTo(hostColonPort)
			if err != nil {
				return nil, err
			}
			if password, _, ok := twoFields(hostColonPort, "@"); ok {
				if password != "" {
					if _, err := conn.Do("AUTH", password); err != nil {
						conn.Close()
						return nil, err
					}
				}
			}
			return conn, err
		},
	}
	pool := ConnectionPool(*redisPool)
	return &pool
}
func SetMaxIdleConnections(maximum int) {
	maxIdleConnections = maximum
}
func (pool *ConnectionPool) Get(dbindex int) redis.Conn {
	redisPool := redis.Pool(*pool)
	conn := redisPool.Get()
	if dbindex != 0 {
		conn.Do("SELECT", strconv.Itoa(dbindex))
	}
	return conn
}
func (pool *ConnectionPool) Ping() error {
	redisPool := redis.Pool(*pool)
	conn := redisPool.Get()
	_, err := conn.Do("PING")
	return err
}
func (pool *ConnectionPool) Close() {
	redisPool := redis.Pool(*pool)
	redisPool.Close()
}
func NewList(pool *ConnectionPool, id string) *List {
	return &List{pool, id, 0}
}
func (rl *List) SelectDatabase(dbindex int) {
	rl.dbindex = dbindex
}
func (rl *List) Get(index int64) (string, error) {
	conn := rl.pool.Get(rl.dbindex)
	result, err := conn.Do("LINDEX", rl.id)
	if err != nil {
		panic(err)
	}
	return redis.String(result, err)
}
func (rl *List) Size() (int64, error) {
	conn := rl.pool.Get(rl.dbindex)
	size, err := conn.Do("LLEN", rl.id)
	if err != nil {
		panic(err)
	}
	return redis.Int64(size, err)
}
func (rl *List) PopFirst() (string, error) {
	conn := rl.pool.Get(rl.dbindex)
	result, err := conn.Do("LPOP", rl.id)
	if err != nil {
		panic(err)
	}
	return redis.String(result, err)
}
func (rl *List) PopLast() (string, error) {
	conn := rl.pool.Get(rl.dbindex)
	result, err := conn.Do("LPOP", rl.id)
	if err != nil {
		panic(err)
	}
	return redis.String(result, err)
}
func (rl *List) AddStart(value string) error {
	conn := rl.pool.Get(rl.dbindex)
	_, err := conn.Do("RPUSH", rl.id, value)
	return err
}
func (rl *List) AddEnd(value string) error {
	conn := rl.pool.Get(rl.dbindex)
	_, err := conn.Do("LPUSH", rl.id, value)
	return err
}
func (rl *List) Add(value string) error {
	return rl.AddStart(value)
}
func (rl *List) All() ([]string, error) {
	conn := rl.pool.Get(rl.dbindex)
	result, err := redis.Values(conn.Do("LRANGE", rl.id, "0", "-1"))
	strs := make([]string, len(result))
	for i := 0; i < len(result); i++ {
		strs[i] = getString(result, i)
	}
	return strs, err
}
func (rl *List) GetAll() ([]string, error) {
	return rl.All()
}
func (rl *List) Last() (string, error) {
	conn := rl.pool.Get(rl.dbindex)
	result, err := redis.Values(conn.Do("LRANGE", rl.id, "-1", "-1"))
	if len(result) == 1 {
		return getString(result, 0), err
	}
	return "", err
}
func (rl *List) GetLast() (string, error) {
	return rl.Last()
}
func (rl *List) LastN(n int) ([]string, error) {
	conn := rl.pool.Get(rl.dbindex)
	result, err := redis.Values(conn.Do("LRANGE", rl.id, "-"+strconv.Itoa(n), "-1"))
	strs := make([]string, len(result))
	for i := 0; i < len(result); i++ {
		strs[i] = getString(result, i)
	}
	return strs, err
}
func (rl *List) GetLastN(n int) ([]string, error) {
	return rl.LastN(n)
}
func (rl *List) RemoveElement(value string) error {
	conn := rl.pool.Get(rl.dbindex)
	_, err := conn.Do("LREM", rl.id, value)
	return err
}
func (rl *List) Set(index int64, value string) error {
	conn := rl.pool.Get(rl.dbindex)
	_, err := conn.Do("LSET", rl.id, index, value)
	return err
}
func (rl *List) Trim(start, stop int64) error {
	conn := rl.pool.Get(rl.dbindex)
	_, err := conn.Do("LTRIM", rl.id, start, stop)
	return err
}
func (rl *List) Remove() error {
	conn := rl.pool.Get(rl.dbindex)
	_, err := conn.Do("DEL", rl.id)
	return err
}
func (rl *List) Clear() error {
	return rl.Remove()
}
func NewSet(pool *ConnectionPool, id string) *Set {
	return &Set{pool, id, 0}
}
func (rs *Set) SelectDatabase(dbindex int) {
	rs.dbindex = dbindex
}
func (rs *Set) Add(value string) error {
	conn := rs.pool.Get(rs.dbindex)
	_, err := conn.Do("SADD", rs.id, value)
	return err
}
func (rs *Set) Size() (int64, error) {
	conn := rs.pool.Get(rs.dbindex)
	size, err := conn.Do("SCARD", rs.id)
	if err != nil {
		panic(err)
	}
	return redis.Int64(size, err)
}
func (rs *Set) Has(value string) (bool, error) {
	conn := rs.pool.Get(rs.dbindex)
	retval, err := conn.Do("SISMEMBER", rs.id, value)
	if err != nil {
		panic(err)
	}
	return redis.Bool(retval, err)
}
func (rs *Set) All() ([]string, error) {
	conn := rs.pool.Get(rs.dbindex)
	result, err := redis.Values(conn.Do("SMEMBERS", rs.id))
	strs := make([]string, len(result))
	for i := 0; i < len(result); i++ {
		strs[i] = getString(result, i)
	}
	return strs, err
}
func (rs *Set) GetAll() ([]string, error) {
	return rs.All()
}
func (rs *Set) Pop() (string, error) {
	conn := rs.pool.Get(rs.dbindex)
	result, err := conn.Do("SPOP", rs.id)
	if err != nil {
		panic(err)
	}
	return redis.String(result, err)
}
func (rs *Set) Random() (string, error) {
	conn := rs.pool.Get(rs.dbindex)
	result, err := conn.Do("SRANDMEMBER", rs.id)
	if err != nil {
		panic(err)
	}
	return redis.String(result, err)
}
func (rs *Set) Del(value string) error {
	conn := rs.pool.Get(rs.dbindex)
	_, err := conn.Do("SREM", rs.id, value)
	return err
}
func (rs *Set) Remove() error {
	conn := rs.pool.Get(rs.dbindex)
	_, err := conn.Do("DEL", rs.id)
	return err
}
func (rs *Set) Clear() error {
	return rs.Remove()
}
func NewHashMap(pool *ConnectionPool, id string) *HashMap {
	return &HashMap{pool, id, 0}
}
func (rh *HashMap) SelectDatabase(dbindex int) {
	rh.dbindex = dbindex
}
func (rh *HashMap) Set(elementid, key, value string) error {
	conn := rh.pool.Get(rh.dbindex)
	_, err := conn.Do("HSET", rh.id+":"+elementid, key, value)
	return err
}
func (rh *HashMap) SetExpire(elementid, key, value string, expire time.Duration) error {
	conn := rh.pool.Get(rh.dbindex)
	if _, err := conn.Do("HSET", rh.id+":"+elementid, key, value); err != nil {
		return err
	}
	go func() {
		time.Sleep(expire)
		rh.DelKey(elementid, key)
	}()
	return nil
}
func (rh *HashMap) Get(elementid, key string) (string, error) {
	conn := rh.pool.Get(rh.dbindex)
	result, err := redis.String(conn.Do("HGET", rh.id+":"+elementid, key))
	if err != nil {
		return "", err
	}
	return result, nil
}
func (rh *HashMap) Has(elementid, key string) (bool, error) {
	conn := rh.pool.Get(rh.dbindex)
	retval, err := conn.Do("HEXISTS", rh.id+":"+elementid, key)
	if err != nil {
		panic(err)
	}
	return redis.Bool(retval, err)
}
func (rh *HashMap) Keys(elementid string) ([]string, error) {
	conn := rh.pool.Get(rh.dbindex)
	result, err := redis.Values(conn.Do("HKEYS", rh.id+":"+elementid))
	strs := make([]string, len(result))
	for i := 0; i < len(result); i++ {
		strs[i] = getString(result, i)
	}
	return strs, err
}
func (rh *HashMap) Exists(elementid string) (bool, error) {
	return hasKey(rh.pool, rh.id+":"+elementid, rh.dbindex)
}
func (rh *HashMap) All() ([]string, error) {
	conn := rh.pool.Get(rh.dbindex)
	result, err := redis.Values(conn.Do("KEYS", rh.id+":*"))
	strs := make([]string, len(result))
	idlen := len(rh.id)
	for i := 0; i < len(result); i++ {
		strs[i] = getString(result, i)[idlen+1:]
	}
	return strs, err
}
func (rh *HashMap) GetAll() ([]string, error) {
	return rh.All()
}
func (rh *HashMap) DelKey(elementid, key string) error {
	conn := rh.pool.Get(rh.dbindex)
	_, err := conn.Do("HDEL", rh.id+":"+elementid, key)
	return err
}
func (rh *HashMap) Del(elementid string) error {
	conn := rh.pool.Get(rh.dbindex)
	_, err := conn.Do("DEL", rh.id+":"+elementid)
	return err
}
func (rh *HashMap) Remove() error {
	conn := rh.pool.Get(rh.dbindex)
	results, err := redis.Values(conn.Do("KEYS", rh.id+":*"))
	if err != nil {
		return err
	}
	for i := 0; i < len(results); i++ {
		if _, err = conn.Do("DEL", getString(results, i)); err != nil {
			return err
		}
	}
	return nil
}
func (rh *HashMap) Clear() error {
	return rh.Remove()
}
func NewKeyValue(pool *ConnectionPool, id string) *KeyValue {
	return &KeyValue{pool, id, 0}
}
func (rkv *KeyValue) SelectDatabase(dbindex int) {
	rkv.dbindex = dbindex
}
func (rkv *KeyValue) Set(key, value string) error {
	conn := rkv.pool.Get(rkv.dbindex)
	_, err := conn.Do("SET", rkv.id+":"+key, value)
	return err
}
func (rkv *KeyValue) SetExpire(key, value string, expire time.Duration) error {
	conn := rkv.pool.Get(rkv.dbindex)
	expireMilliseconds := expire.Nanoseconds() / 1000000
	_, err := conn.Do("SET", rkv.id+":"+key, value, "PX", expireMilliseconds)
	return err
}
func (rkv *KeyValue) TimeToLive(key string) (time.Duration, error) {
	conn := rkv.pool.Get(rkv.dbindex)
	ttlSecondsInterface, err := conn.Do("TTL", rkv.id+":"+key)
	if err != nil || ttlSecondsInterface.(int64) <= 0 {
		return time.Duration(0), err
	}
	ns := time.Duration(ttlSecondsInterface.(int64)) * time.Second
	return ns, nil
}
func (rkv *KeyValue) Get(key string) (string, error) {
	conn := rkv.pool.Get(rkv.dbindex)
	result, err := redis.String(conn.Do("GET", rkv.id+":"+key))
	if err != nil {
		return "", err
	}
	return result, nil
}
func (rkv *KeyValue) Del(key string) error {
	conn := rkv.pool.Get(rkv.dbindex)
	_, err := conn.Do("DEL", rkv.id+":"+key)
	return err
}
func (rkv *KeyValue) Inc(key string) (string, error) {
	conn := rkv.pool.Get(rkv.dbindex)
	result, err := redis.Int64(conn.Do("INCR", rkv.id+":"+key))
	if err != nil {
		return "0", err
	}
	return strconv.FormatInt(result, 10), nil
}
func (rkv *KeyValue) Remove() error {
	conn := rkv.pool.Get(rkv.dbindex)
	results, err := redis.Values(conn.Do("KEYS", rkv.id+":*"))
	if err != nil {
		return err
	}
	for i := 0; i < len(results); i++ {
		if _, err = conn.Do("DEL", getString(results, i)); err != nil {
			return err
		}
	}
	return nil
}
func (rkv *KeyValue) Clear() error {
	return rkv.Remove()
}
func hasKey(pool *ConnectionPool, wildcard string, dbindex int) (bool, error) {
	conn := pool.Get(dbindex)
	result, err := redis.Values(conn.Do("KEYS", wildcard))
	if err != nil {
		return false, err
	}
	return len(result) > 0, nil
}
func SetConnectTimeout(t time.Duration) {
	connectTimeout = t
}
func SetReadTimeout(t time.Duration) {
	readTimeout = t
}
func SetWriteTimeout(t time.Duration) {
	writeTimeout = t
}
func SetIdleTimeout(t time.Duration) {
	idleTimeout = t
}