package storage

import (
	"fmt"
	"strconv"
	"strings"
)

type DB interface {
	Get(string, ...string) ([]byte, error)
	Set(string, []byte, ...string) error
	List([]string, ...string) ([]string, error)
	Close() error
}

var DefaultNamespace = "namespace"

func New(key Type, params ...string) (db DB, err error) {
	defer func() {
		if i := recover(); i != nil {
			err = fmt.Errorf("panic making %s: %v", key, i)
		}
	}()
	err = ErrNotImpl
	switch key {
	case DYNOMITE:
		db, err = NewDynomite(params[0], params[1], params[2])
	case REDIS:
		db, err = NewRedis(params[0], params[1], params[2])
	case MAP:
		db = NewMap()
		err = nil
	case BOLT:
		db, err = NewBolt(params[0])
	case MINIO:
		db, err = NewMinio(params[0], params[1], params[2])
	case CACHE:
		db, err = NewCache(params...)
	case LEVELDB:
		db, err = NewLevelDB(params[0])
	case MEMCACHE:
		db, err = NewMemcache(params[0], params[1:]...)
	case MEMCACHECLUSTER:
		db, err = NewMemcacheCluster(params[0], params[1:]...)
	case MONGO:
		db, err = NewMongo(params[0], params[1:]...)
	}
	return
}

func resolveNamespace(ns []string) string {
	namespace := DefaultNamespace
	if len(ns) > 0 {
		segments := []string{}
		for i := range ns {
			if ns[i] != "" {
				segments = append(segments, ns[i])
			}
		}
		namespace = strings.Join(segments, ".")
	}
	return namespace
}

func resolveLimits(input []string) []string {
	return []string{
		resolveLimitsStart(input),
		resolveLimitsStop(input),
		resolveLimitsLimit(input),
		resolveLimitsAscending(input),
	}
}

func resolveLimitsStart(input []string) string {
	if len(input) > 0 {
		return input[0]
	}
	return " "
}

func resolveLimitsStop(input []string) string {
	if len(input) > 1 {
		return input[1]
	}
	return "}}}}}}"
}

func resolveLimitsLimit(input []string) string {
	if len(input) > 2 {
		v, _ := strconv.Atoi(input[2])
		return strconv.Itoa(v)
	}
	return "0"
}

func resolveLimitsAscending(input []string) string {
	return strconv.FormatBool(len(input) < 4 || input[3] != "-")
}
