package storage

import (
	"errors"
	"net"
	"path"

	"github.com/bradfitz/gomemcache/memcache"
)

type Memcache struct {
	db *memcache.Client
}

type netAddr struct {
	network string
	addr    string
}

func (a *netAddr) Network() string {
	return a.network
}

func (a *netAddr) String() string {
	return a.addr
}

func NewMemcache(addr string, addrs ...string) (*Memcache, error) {
	for i := len(addrs) - 1; i >= 0; i-- {
		if len(addrs[i]) == 0 {
			addrs = append(addrs[:i], addrs[i+1:]...)
		}
	}
	ss := &memcache.ServerList{}
	if err := ss.SetServers(append([]string{addr}, addrs...)...); err != nil {
		return nil, err
	}
	if err := ss.Each(func(addr net.Addr) error {
		conn, err := net.Dial("tcp", addr.String())
		if err != nil {
			return err
		}
		return conn.Close()
	}); err != nil {
		return nil, err
	}
	db := memcache.NewFromSelector(ss)
	return &Memcache{db: db}, nil
}

func (mc *Memcache) List(ns []string, limits ...string) ([]string, error) {
	return nil, errors.New("not impl")
}

func (mc *Memcache) Get(key string, ns ...string) ([]byte, error) {
	namespace := resolveNamespace(ns)
	v, err := mc.db.Get(path.Join(namespace, key))
	if err != nil {
		return nil, err
	}
	if v == nil {
		return nil, ErrNotFound
	}
	return v.Value, err
}

func (mc *Memcache) Set(key string, value []byte, ns ...string) error {
	namespace := resolveNamespace(ns)
	return mc.db.Set(&memcache.Item{
		Key:   path.Join(namespace, key),
		Value: value,
	})
}

func (mc *Memcache) Close() error {
	return mc.db.FlushAll()
}
