package tins2020

import (
	"fmt"
	"strconv"
)

type Herbarium struct {
	flowers map[string]FlowerDescriptor
	order   []string
}

func NewHerbarium() Herbarium {
	h := Herbarium{map[string]FlowerDescriptor{}, nil}
	h.Reset()
	return h
}

func (h *Herbarium) Reset() {
	h.flowers = map[string]FlowerDescriptor{}
	h.order = nil

	h.Add("anemone", FlowerDescriptor{
		Name:         "Anemone",
		Description:  "A very generic flower that thrives in a temperate climate.",
		IconTemplate: "flower-anemone-%s",
		BuyPrice:     10,
		SellPrice:    3,
		Traits:       NewAnemoneTraits(),
		Unlocked:     true,
	})
	h.Add("loosestrife", FlowerDescriptor{
		Name:         "Loosestrife",
		Description:  "A simple flower that will spread in temperate and wet climates.",
		IconTemplate: "flower-loosestrife-%s",
		BuyPrice:     100,
		SellPrice:    20,
		Traits:       NewLoosestrifeTraits(),
		Unlocked:     false,
	})
	h.Add("coneflower", FlowerDescriptor{
		Name:         "Coneflower",
		Description:  "A beautifull flower that can withstand hotter climates.",
		IconTemplate: "flower-coneflower-%s",
		BuyPrice:     500,
		SellPrice:    100,
		Traits:       NewConeflowerTraits(),
		Unlocked:     false,
	})
	h.Add("tulip", FlowerDescriptor{
		Name:         "Tulip",
		Description:  "A lovely flower that prefers a bit humid and colder climates.",
		IconTemplate: "flower-tulip-%s",
		BuyPrice:     20000,
		SellPrice:    5000,
		Traits:       NewTulipTraits(),
		Unlocked:     false,
	})
	h.Add("ajuga", FlowerDescriptor{
		Name:         "Ajuga",
		Description:  "A flower that is resitant to cold climates and spreads very easily.",
		IconTemplate: "flower-ajuga-%s",
		BuyPrice:     100000,
		SellPrice:    10000,
		Traits:       NewAjugaTraits(),
		Unlocked:     false,
	})
}

func (h *Herbarium) Update(id string, update func(*FlowerDescriptor)) {
	flower, ok := h.flowers[id]
	if !ok {
		return
	}
	update(&flower)
	h.flowers[id] = flower
}

type FlowerDescriptor struct {
	Name        string
	Description string
	BuyPrice    int
	SellPrice   int

	Unlocked     bool
	IconTemplate IconTemplate
	Traits       FlowerTraits
}

type IconTemplate string

func (t IconTemplate) Disabled() string { return t.Fmt("disabled") }

func (t IconTemplate) Fmt(s string) string { return fmt.Sprintf(string(t), s) }

func (t IconTemplate) Variant(i int) string { return t.Fmt(strconv.Itoa(i)) }

func (h *Herbarium) Add(id string, desc FlowerDescriptor) {
	h.flowers[id] = desc
	h.order = append(h.order, id)
}

func (h *Herbarium) Find(id string) (FlowerDescriptor, bool) {
	flower, ok := h.flowers[id]
	return flower, ok
}

func (h *Herbarium) Flowers() []string { return h.order }

func (h *Herbarium) IsUnlocked(id string) bool {
	flower, ok := h.flowers[id]
	if !ok {
		return false
	}
	return flower.Unlocked
}

func (h *Herbarium) NextFlowerToUnlock() (string, FlowerDescriptor, int) {
	var previous *FlowerDescriptor
	for _, id := range h.Flowers() {
		flower, _ := h.Find(id)
		if !flower.Unlocked {
			if previous == nil {
				return "", FlowerDescriptor{}, 0
			}
			return id, flower, previous.BuyPrice * 2
		}
		previous = &flower
	}
	return "", FlowerDescriptor{}, 0
}

func (h *Herbarium) UnlockNext() int {
	id, flower, price := h.NextFlowerToUnlock()
	if len(id) == 0 {
		return 0
	}
	flower.Unlocked = true
	h.flowers[id] = flower
	return price
}