package controller

import (
	"galaxy/game/internal/model/game"

	"github.com/google/uuid"
)

func (c *Cache) ProduceBombings() []*game.Bombing {
	report := make([]*game.Bombing, 0)
	for pn, enemies := range c.collectBombingGroups() {
		p := c.MustPlanet(pn)
		if !p.Owned() {
			continue
		}
		for ri, groups := range enemies {
			br := c.bombingReport(p, ri, groups)
			report = append(report, br)
			if br.Wiped {
				break
			}
		}

		if p.Population == 0 {
			p.Free()
		} else {
			// Если на планете остались также и колонисты, то они превращаются в население,
			// а накопленная промышленность возмещает потери производства.
			p.UnpackColonists()
			p.UnpackCapital()
		}
	}
	return report
}

func (c *Cache) bombingReport(p *game.Planet, ri int, groups []int) *game.Bombing {
	attackPower := 0.
	for _, i := range groups {
		sg := c.ShipGroup(i)
		st := c.ShipGroupShipClass(i)
		attackPower += sg.BombingPower(st)
	}
	r := &game.Bombing{
		ID:            uuid.New(),
		PlanetOwnedID: *p.Owner,
		Planet:        p.Name,
		Number:        p.Number,
		Owner:         c.g.Race[c.RaceIndex(*p.Owner)].Name,
		Attacker:      c.g.Race[ri].Name,
		Production:    c.PlanetProductionDisplayName(p.Number),
		Industry:      p.Industry,
		Population:    p.Population,
		Colonists:     p.Colonists,
		Capital:       p.Capital,
		Material:      p.Material,
		AttackPower:   game.F(attackPower),
	}
	bombPlanet(p, attackPower)
	r.Wiped = p.Population == 0
	return r
}

func bombPlanet(p *game.Planet, power float64) {
	// Уничтожается население и колонисты в количестве равном [суммарной] мощности бомбардировки
	if power > p.Population.F() {
		p.Pop(0)
	} else {
		p.Pop(p.Population.F() - power)
	}
	if power > p.Colonists.F() {
		p.Col(0)
	} else {
		p.Col(p.Colonists.F() - power)
	}
	// Такое же количество промышленности превращается в сырье
	if power > p.Industry.F() {
		p.Mat(p.Material.F() + p.Industry.F())
		p.Ind(0)
	} else {
		p.Mat(p.Material.F() + power)
		p.Ind(p.Industry.F() - power)
	}
}

// [planet_num] -> [enemy_race_id] -> []group_id
func (c *Cache) collectBombingGroups() map[uint]map[int][]int {
	result := make(map[uint]map[int][]int)
	for i := range c.ShipGroupsIndex() {
		sg := c.ShipGroup(i)
		if sg.State() != game.StateInOrbit {
			continue
		}
		st := c.ShipGroupShipClass(i)
		if st.WeaponsBlockMass() == 0 {
			continue
		}
		p := c.MustPlanet(sg.Destination)
		if p.OwnedBy(sg.OwnerID) || !p.Owned() {
			continue
		}
		r1 := c.RaceIndex(sg.OwnerID)
		r2 := c.RaceIndex(*p.Owner)
		if c.Relation(r1, r2) == game.RelationPeace {
			continue
		}
		// add result
		if _, ok := result[p.Number]; !ok {
			result[p.Number] = make(map[int][]int)
		}
		result[p.Number][r1] = append(result[p.Number][r1], i)
	}
	return result
}
