// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      Magicbane Emulator Project © 2013 - 2022
//                www.magicbane.com


package engine.workthreads;

/*
 * This thread is spawned to process destruction
 * of a player owned city, including subguild
 * and database cleanup.
 *
 * The 'destroyed' city zone persists until the
 * next reboot.
 */

import engine.Enum;
import engine.gameManager.DbManager;
import engine.gameManager.GuildManager;
import engine.gameManager.ZoneManager;
import engine.math.Vector3fImmutable;
import engine.objects.Building;
import engine.objects.City;
import engine.objects.Guild;
import engine.objects.Zone;
import org.pmw.tinylog.Logger;

import java.util.ArrayList;

public class DestroyCityThread implements Runnable {

    City city;

    public DestroyCityThread(City city) {

        this.city = city;
    }

    public void run() {

        // Member variable declaration

        Zone cityZone;
        Zone newParent;
        Guild formerGuild;
        Vector3fImmutable localCoords;
        ArrayList<Guild> subGuildList;

        // Member variable assignment

        cityZone = city.getParent();
        newParent = cityZone.getParent();
        formerGuild = city.getTOL().getGuild();

        // Former guild loses it's tree!

        if (DbManager.GuildQueries.SET_GUILD_OWNED_CITY(formerGuild.getObjectUUID(), 0)) {

            //Successful Update of guild

            formerGuild.setGuildState(engine.Enum.GuildState.Errant);
            formerGuild.setNation(null);
            formerGuild.setCityUUID(0);
            GuildManager.updateAllGuildTags(formerGuild);
            GuildManager.updateAllGuildBinds(formerGuild, null);
        }

        // By losing the tree, the former owners lose all of their subguilds.

        if (formerGuild.getSubGuildList().isEmpty() == false) {

            subGuildList = new ArrayList<>();

            for (Guild subGuild : formerGuild.getSubGuildList()) {
                subGuildList.add(subGuild);
            }

            for (Guild subGuild : subGuildList) {
                formerGuild.removeSubGuild(subGuild);
            }
        }

        // Build list of buildings within this parent zone

        for (Building cityBuilding : cityZone.zoneBuildingSet) {

            // Sanity Check in case player deletes the building
            // before this thread can get to it

            if (cityBuilding == null)
                continue;

            // Do nothing with the banestone.  It will be removed elsewhere

            if (cityBuilding.getBlueprint().getBuildingGroup().equals(Enum.BuildingGroup.BANESTONE))
                continue;

            // All buildings are moved to a location relative
            // to their new parent zone

            localCoords = ZoneManager.worldToLocal(cityBuilding.getLoc(), newParent);

            DbManager.BuildingQueries.MOVE_BUILDING(cityBuilding.getObjectUUID(), newParent.getObjectUUID(), localCoords.x, localCoords.y, localCoords.z);

            // All buildings are re-parented to a zone one node
            // higher in the tree (continent) as we will be
            // deleting the city zone very shortly.

            if (cityBuilding.getParentZoneID() != newParent.getParentZoneID())
                cityBuilding.setParentZone(newParent);

            // No longer a tree, no longer any protection contract!

            cityBuilding.setProtectionState(Enum.ProtectionState.NONE);

            // Destroy all remaining city assets

            if ((cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.BARRACK)
                    || (cityBuilding.getBlueprint().isWallPiece())
                    || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SHRINE)
                    || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.TOL)
                    || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.SPIRE)
                    || (cityBuilding.getBlueprint().getBuildingGroup() == Enum.BuildingGroup.WAREHOUSE)) {

                if (cityBuilding.getRank() != -1)
                    cityBuilding.setRank(-1);
            }
        }

        if (city.getRealm() != null)
            city.getRealm().removeCity(city.getObjectUUID());

        // It's now safe to delete the city zone from the database
        // which will cause a cascade delete of everything else


        if (DbManager.ZoneQueries.DELETE_ZONE(cityZone) == false) {
            Logger.error("DestroyCityThread", "Database error when deleting city zone: " + cityZone.getObjectUUID());
            return;
        }

        // Refresh the city for map requests

        City.lastCityUpdate = System.currentTimeMillis();

        // Zone and city should vanish upon next reboot
        // if the codebase reaches here.

        Logger.info(city.getParent().getName() + " uuid:" + city.getObjectUUID() + "has been destroyed!");
    }
}
