package env

import (
	"fmt"
	"log"
	"os"
	"sort"
	"strconv"
)

type Env struct {
	fallback map[string]string
	current  map[string]string
}

func New() *Env {
	return &Env{
		fallback: map[string]string{},
		current:  map[string]string{},
	}
}

func (e *Env) Get(key, fallback string) string {
	e.fallback[key] = fallback
	e.current[key] = fallback
	if value, ok := os.LookupEnv(key); ok {
		e.current[key] = value
		return value
	}
	return fallback
}

func (e *Env) GetUInt(key string, fallback uint) uint {
	e.fallback[key] = fmt.Sprint(fallback)
	e.current[key] = fmt.Sprint(fallback)
	if value, ok := os.LookupEnv(key); ok {
		uvalue, err := strconv.Atoi(value)
		if err != nil {
			log.Fatal(err)
		}
		if uvalue <= 0 {
			log.Fatalf("env %s need to greater than 0", key)
		}
		e.current[key] = fmt.Sprint(uvalue)
		return uint(uvalue)
	}
	return fallback
}

type Result struct {
	Key   string
	Value string
}

func (e *Env) sort(o map[string]string) []Result {
	r := make([]Result, 0, len(o))
	for k := range o {
		r = append(r, Result{k, o[k]})
	}
	sort.Slice(r, func(i, j int) bool {
		return r[i].Key < r[j].Key
	})
	return r
}

func (e *Env) Current() []Result {
	return e.sort(e.current)
}

func (e *Env) Fallback() []Result {
	return e.sort(e.fallback)
}