package controller

import (
	"galaxy/calc"
	e "galaxy/error"

	"galaxy/game/internal/model/game"
)

func (c *Cache) FleetSend(ri, fi int, planetNumber uint) error {
	c.validateRaceIndex(ri)
	c.validateFleetIndex(fi)
	fleetState := c.FleetState(c.g.Fleets[fi].ID)
	sourcePlanet, ok := fleetState.AtPlanet()
	if !ok || game.StateInOrbit != fleetState.State && game.StateLaunched != fleetState.State {
		return e.NewShipsBusyError("state: %s", fleetState.State)
	}

	p1, ok := c.Planet(sourcePlanet)
	if !ok {
		return e.NewGameStateError("source planet #%d does not exists", sourcePlanet)
	}
	p2, ok := c.Planet(planetNumber)
	if !ok {
		return e.NewEntityNotExistsError("destination planet #%d", planetNumber)
	}
	rangeToDestination := calc.ShortDistance(c.g.Map.Width, c.g.Map.Height, p1.X.F(), p1.Y.F(), p2.X.F(), p2.Y.F())
	if rangeToDestination > c.g.Race[ri].FlightDistance() {
		return e.NewSendUnreachableDestinationError("range=%.03f", rangeToDestination)
	}

	for sgi := range c.FleetGroupIdx(ri, fi) {
		st := c.MustShipType(ri, c.ShipGroup(sgi).TypeID)
		if st.DriveBlockMass() == 0 {
			return e.NewSendShipHasNoDrivesError("Class=%s", st.Name)
		}
	}

	if sourcePlanet == planetNumber {
		c.UnsendFleet(ri, fi)
		return nil
	}

	c.LaunchFleet(ri, fi, planetNumber)

	return nil
}

func (c *Cache) LaunchFleet(ri, fi int, destination uint) {
	c.validateRaceIndex(ri)
	c.validateFleetIndex(fi)
	for sgi := range c.FleetGroupIdx(ri, fi) {
		c.LaunchShips(sgi, destination)
	}
}

func (c *Cache) UnsendFleet(ri, fi int) {
	c.validateRaceIndex(ri)
	c.validateFleetIndex(fi)
	for sgi := range c.FleetGroupIdx(ri, fi) {
		c.UnsendShips(sgi)
	}
}
