package game

import (
	"github.com/google/uuid"
)

type Planet struct {
	X          Float              `json:"x"`
	Y          Float              `json:"y"`
	Number     uint               `json:"number"`
	Size       Float              `json:"size"`
	Name       string             `json:"name"`
	Owner      *uuid.UUID         `json:"owner,omitempty"`
	Resources  Float              `json:"resources"`  // R - Ресурсы
	Capital    Float              `json:"capital"`    // CAP $ - Запасы промышленности
	Material   Float              `json:"material"`   // MAT M - Запасы ресурсов / сырьё
	Industry   Float              `json:"industry"`   // I - Промышленность
	Population Float              `json:"population"` // P - Население
	Colonists  Float              `json:"colonists"`  // COL C - Количество колонистов
	Production Production         `json:"production"`
	Route      map[RouteType]uint `json:"route"`
}

func (p *Planet) Own(v uuid.UUID) {
	if v == uuid.Nil {
		p.Free()
		return
	}
	if p.Owner == nil || *p.Owner != v {
		p.Production = ProductionCapital.AsType(uuid.Nil)
	}
	p.Owner = &v
}

func (p *Planet) Free() {
	p.Owner = nil
	p.Production = ProductionNone.AsType(uuid.Nil)
	p.Colonists = 0.
	p.Population = 0.
	clear(p.Route)
}

func (p *Planet) Wipe() {
	p.Free()
	p.Industry = 0
	p.Capital = 0
}

func (p Planet) Owned() bool {
	return p.Owner != nil && *p.Owner != uuid.Nil
}

func (p Planet) OwnedBy(v uuid.UUID) bool {
	if !p.Owned() {
		return false
	}
	return *p.Owner == v
}

func (p *Planet) Mat(v float64) {
	p.Material = F(v)
}

func (p *Planet) Pop(v float64) {
	p.Population = F(v)
}

func (p *Planet) Col(v float64) {
	p.Colonists = F(v)
}

func (p *Planet) Ind(v float64) {
	p.Industry = F(v)
}

func (p *Planet) Cap(v float64) {
	p.Capital = F(v)
}

func (p Planet) Votes() float64 {
	return p.Population.F() / 1000.
}

// Производственный потенциал без учёта модернизации кораблей
func (p Planet) ProductionCapacity() float64 {
	return PlanetProduction(p.Industry.F(), p.Population.F())
}

func PlanetProduction(industry, population float64) float64 {
	return industry*0.75 + population*0.25
}

func (p *Planet) ReleaseMaterial(shipMass float64) {
	if p.Production.Type != ProductionShip || p.Production.Progress == nil {
		panic("planet is not producing any ships")
	}
	p.Material = p.Material.Add(ProducedMaterial(shipMass, float64(*p.Production.Progress)))
	p.Production.Progress = new(Float)
	p.Production.ProdUsed = new(Float)
}

func ProducedMaterial(shipMass, progress float64) float64 {
	return shipMass * progress
}

// Производство промышленности
func (p *Planet) ProduceIndustry(freeProduction float64) {
	prod := freeProduction / 5
	if float64(p.Material) < prod {
		prod = (freeProduction + float64(p.Material/p.Resources)) / (5. + 1./float64(p.Resources))
		p.Material = 0.
	} else {
		p.Material = p.Material.Add(-prod)
	}
	p.Industry = p.Industry.Add(prod)
	if p.Industry > p.Population {
		p.Capital += p.Industry - p.Population
		p.Industry = p.Population
	}
}

// Производство материалов
func (p *Planet) ProduceMaterial(freeProduction float64) {
	p.Material = p.Material.Add(freeProduction * p.Resources.F())
}

// Автоматическое увеличение населения на каждом ходу
func (p *Planet) ProducePopulation() {
	p.Population *= 1.08
	if p.Population > p.Size {
		p.Colonists += (p.Population - p.Size) / 8.
		p.Population = p.Size
	}
}

func (p *Planet) UnpackCapital() {
	if p.Capital == 0 {
		return
	}
	deficit := p.Population - p.Industry
	if deficit > p.Capital {
		deficit = p.Capital
	}
	p.Capital -= deficit
	p.Industry += deficit
}

func (p *Planet) UnpackColonists() {
	if p.Colonists == 0 {
		return
	}
	deficit := (p.Size - p.Population) / 8
	if deficit > p.Colonists {
		deficit = p.Colonists
	}
	p.Colonists -= deficit
	p.Population += deficit * 8
}

func UnloadColonists(p Planet, v float64) Planet {
	p.Pop(p.Population.F() + v*8)
	if p.Population > p.Size {
		p.Col(p.Colonists.F() + (p.Population.F()-p.Size.F())/8.)
		p.Pop(p.Size.F())
	}
	return p
}
