package main

import (
	"encoding/json"
	"fmt"
	"math"
	"math/rand/v2"
	"os"
	"strings"

	"github.com/fogleman/gg"
)

type Lane int

const (
	Any Lane = iota
	Red
	Green
	Blue
)

type Type int

const (
	Unit Type = iota
	Spell
	Boon
)

func (l Lane) String() string {
	switch l {
	case Any:
		return "⬜ Boon"
	case Red:
		return "🟥 Red"
	case Green:
		return "🟩 Green"
	case Blue:
		return "🟦 Blue"
	default:
		panic("unknwon")
	}
}

func (t Type) String() string {
	switch t {
	case Unit:
		return "Unit"
	case Boon:
		return "Boon"
	case Spell:
		return "Spell"
	default:
		panic("unknown")
	}
}

func main() {
	type (
		jsonfront struct {
			Name       string `json:"name"`
			Type       string `json:"type"`
			Cost       int    `json:"cost"`
			Image      string `json:"image"`
			Horizontal bool   `json:"isHorizontal"`
		}
		jsoncard struct {
			// required
			Id   string `json:"id"`
			Face struct {
				Front jsonfront `json:"front"`
			} `json:"face"`
			Name  string `json:"name"`
			Type  string `json:"type"`
			Cost  int    `json:"cost"`
			Token bool   `json:"isToken"`

			// custom
			Lane    string          `json:"Lane"`
			Entropy int             `json:"Entropy"`
			Force   int             `json:"Force"`
			Legal   map[string]bool `json:"_legal"`
		}
	)

	thejson := make(map[string]jsoncard)
	for i := range len(CARDS) {
		card := &CARDS[i]
		if len(card.name) == 0 {
			card.name = generateTemporaryName()
		}

		var (
			baseimg string
			color   [3]float64
		)
		switch card.lane {
		case Red:
			baseimg = "base-red.png"
			color = [3]float64{248.0 / 255.0, 120.0 / 255.0, 143.0 / 255.0}
		case Green:
			baseimg = "base-green.png"
			color = [3]float64{126.0 / 255.0, 229.0 / 255.0, 166.0 / 255.0}
		case Blue:
			baseimg = "base-blue.png"
			color = [3]float64{120.0 / 255.0, 190.0 / 255.0, 248.0 / 255.0}
		default:
			color = [3]float64{184.0 / 255.0, 184.0 / 255.0, 184.0 / 255.0}
			baseimg = "base-boon.png"
		}

		img, err := gg.LoadImage("docs/" + baseimg)
		if err != nil {
			panic(err)
		}

		ctx := gg.NewContextForImage(img)
		if err := ctx.LoadFontFace("docs/SFCamera.ttf", 80); err != nil {
			panic(err)
		}

		// Draw force
		if card.typ != Boon {
			ctx.SetRGB(1, 1, 1)
			ctx.Push()
			{
				ctx.Translate(160, 155)
				ctx.Rotate(270 * math.Pi / 180)
				ctx.DrawStringAnchored(fmt.Sprintf("%d", card.force), 0, 0, 0.5, 0.5)
			}
			ctx.Pop()
		}

		// Draw entropy or recovery
		ctx.SetRGB(color[0], color[1], color[2])
		ctx.Push()
		{
			ctx.Translate(360, 155)
			ctx.Rotate(270 * math.Pi / 180)
			ctx.DrawStringAnchored(fmt.Sprintf("%d", max(card.entropy, card.recovery)), 0, 0, 0.5, 0.5)
		}
		ctx.Pop()

		if err := ctx.LoadFontFace("docs/SFCamera.ttf", 36); err != nil {
			panic(err)
		}

		// Draw description
		cleandesc := strings.NewReplacer("{{", "", "}}", "").Replace(card.desc)
		ctx.SetRGBA(0, 0, 0, 0.9)
		ctx.Push()
		{
			ctx.Translate(585, 1325)
			ctx.Rotate(270 * math.Pi / 180)
			ctx.DrawStringWrapped(fmt.Sprintf("#%03d %s - %s\n%s", i, card.name, card.typ.String(), cleandesc), 0, 0, 0.0, 0.0, 900, 1.80, gg.AlignLeft)
		}
		ctx.Pop()

		id := fmt.Sprintf("%03d", i)

		// draw rotated
		// finished := ctx.Image()
		// w := finished.Bounds().Dx()
		// h := finished.Bounds().Dy()
		// rotated := gg.NewContext(h, w)
		// rotated.Translate(float64(h)/2, float64(w)/2)
		// rotated.Rotate(90 * math.Pi / 180)
		// rotated.DrawImageAnchored(finished, 0, 0, 0.5, 0.5)

		if err := ctx.SavePNG("docs/" + id + ".png"); err != nil {
			panic(err)
		}

		thejson[id] = jsoncard{
			Id: id,
			Face: struct {
				Front jsonfront `json:"front"`
			}{
				jsonfront{
					Name:       card.name,
					Type:       card.typ.String(),
					Image:      fmt.Sprintf("https://docs.brut.systems/judah/entropy/%s.png", id),
					Cost:       card.entropy,
					Horizontal: true,
				},
			},
			Token: card.token,
			Name:  card.name,
			Type:  card.typ.String(),
			Cost:  card.entropy,

			Entropy: card.entropy,
			Force:   card.force,
			Lane:    card.lane.String(),
			Legal: map[string]bool{
				"playtest": true,
			},
		}
	}

	enc, err := json.MarshalIndent(thejson, "", "  ")
	if err != nil {
		panic(err)
	}

	if err := os.WriteFile("CardList.json", enc, 0644); err != nil {
		panic(err)
	}
}

func generateTemporaryName() string {
	var (
		adjectives = []string{
			"Absent",
			"Ambient",
			"Bare",
			"Blunt",
			"Civic",
			"Composite",
			"Concave",
			"Dull",
			"Errant",
			"Excess",
			"Flat",
			"Former",
			"Gross",
			"Inland",
			"Lateral",
			"Live",
			"Lucid",
			"Moot",
			"Vampiric",
			"Nominal",
			"Convergent",
			"Partial",
			"Boon",
			"Raging",
			"Polar",
			"Residual",
			"Rote",
			"Soft",
			"Spent",
			"Terminal",
			"Warm",
		}
		nouns = []string{
			"Aperture",
			"Axis",
			"Bulk",
			"Cartilage",
			"Compact",
			"Contour",
			"Conviction",
			"Cortex",
			"Deficit",
			"Dividend",
			"Dosage",
			"Shrine",
			"Filament",
			"Gesture",
			"Gradient",
			"Inlet",
			"Judgement",
			"Mandate",
			"Membrane",
			"Morale",
			"Offset",
			"Posture",
			"Precinct",
			"Prospect",
			"Rapport",
			"Reflex",
			"Mutation",
			"Substrate",
			"Surplus",
			"Tendon",
			"Volume",
		}
	)

	return adjectives[rand.IntN(len(adjectives))] + nouns[rand.IntN(len(nouns))]
}
