package namer

import (
	"fmt"
)

var (
	local Generator
)

func Seed(seed int64) {
	local = NewGenerator(seed)
}

func Register(fs ...Format) {
	for _, f := range fs {
		_ = local.Register(f.ident(), f.randomOptions())
	}
}

type Format interface {
	ident() string
	randomOptions() *Options
	format() string
}

type Namer interface {
	Name() string
}

type Global string

func (r Global) Namer() Namer {
	return &namer{
		g:      local,
		ident:  r.ident(),
		format: r.format(),
	}
}

func (r Global) ident() string {
	return string(r)
}

func (r Global) randomOptions() *Options {
	return &Options{
		N:       5,
		Charset: []byte(defaultCharset),
	}
}

func (r Global) format() string {
	return "I-R"
}

type Zonal string

func (r Zonal) Namer(zone string) Namer {
	return &namer{
		g:      local,
		ident:  r.ident(),
		format: r.format(),
		zone:   zone,
	}
}

func (r Zonal) ident() string {
	return string(r)
}

func (r Zonal) randomOptions() *Options {
	return &Options{
		N:       5,
		Charset: []byte(defaultCharset),
	}
}

func (r Zonal) format() string {
	return "I-R-Z"
}

type Reconciler string

func (r Reconciler) Namer(reconciler string) Namer {
	return &namer{
		g:      local,
		ident:  r.ident(),
		format: r.format(),

		reconciler: reconciler,
	}
}

func (r Reconciler) ident() string {
	return string(r)
}

func (r Reconciler) randomOptions() *Options {
	return &Options{
		N:       5,
		Charset: []byte(defaultCharset),
	}
}

func (r Reconciler) format() string {
	return "I-R-V"
}

// TODO: refactor, it's weird
// I: ident
// R: random string
// Z: zone
// V: reconciler
type namer struct {
	g      Generator
	format string
	ident  string

	zone       string
	reconciler string
}

func (n *namer) Name() string {
	s := n.g.Get(n.ident)
	switch n.format {
	case "I-R":
		return fmt.Sprintf("%s-%s", n.ident, s)
	case "I-R-Z":
		return fmt.Sprintf("%s-%s-%s", n.ident, s, n.zone)
	case "I-R-V":
		return fmt.Sprintf("%s-%s-%s", n.ident, s, n.reconciler)
	default:
		return n.ident
	}
}
