package game

import (
	"encoding/json"
	"fmt"
	"maps"

	"galaxy/util"

	"github.com/google/uuid"
)

type Float float64

func F(v float64) Float {
	return Float(v)
}

func (f Float) Add(v float64) Float {
	return f + F(v)
}

func (f Float) F() float64 {
	return util.Fixed12(float64(f))
}

type TechSet map[Tech]Float

func (ts TechSet) Value(t Tech) float64 {
	if v, ok := ts[t]; ok {
		return v.F()
	} else {
		panic(fmt.Sprintf("TechSet: Value: %s's value not set", t.String()))
	}
}

func (ts TechSet) Set(t Tech, v float64) TechSet {
	m := maps.Clone(ts)
	m[t] = F(v)
	return m
}

func NewTechSet() TechSet {
	return TechSet{
		TechDrive:   1.,
		TechWeapons: 1.,
		TechShields: 1.,
		TechCargo:   1.,
	}
}

type Game struct {
	ID         uuid.UUID   `json:"id"`
	Turn       uint        `json:"turn"`
	Stage      uint        `json:"stage"`
	Map        Map         `json:"map"`
	Race       []Race      `json:"races"`
	Votes      Float       `json:"votes"`
	ShipGroups []ShipGroup `json:"shipGroup,omitempty"`
	Fleets     []Fleet     `json:"fleet,omitempty"`
	Winner     []uuid.UUID `json:"winner,omitempty"`
}

func (g Game) Finished() bool {
	return len(g.Winner) > 0
}

type GameMeta struct {
	Battles  []BattleMeta `json:"battles,omitempty"`
	Bombings []Bombing    `json:"bombings,omitempty"`
}

type BattleMeta struct {
	Turn        uint        `json:"turn"`
	Planet      uint        `json:"planet"`
	BattleID    uuid.UUID   `json:"battle_id"`
	ObserverIDs []uuid.UUID `json:"observer_ids"`
}

func (g Game) MarshalBinary() (data []byte, err error) {
	return json.Marshal(&g)
}

func (g *Game) UnmarshalBinary(data []byte) error {
	return json.Unmarshal(data, g)
}

func (gm GameMeta) MarshalBinary() (data []byte, err error) {
	return json.Marshal(&gm)
}

func (gm *GameMeta) UnmarshalBinary(data []byte) error {
	return json.Unmarshal(data, gm)
}
