// • ▌ ▄ ·.  ▄▄▄·  ▄▄ • ▪   ▄▄· ▄▄▄▄·  ▄▄▄·  ▐▄▄▄  ▄▄▄ .
// ·██ ▐███▪▐█ ▀█ ▐█ ▀ ▪██ ▐█ ▌▪▐█ ▀█▪▐█ ▀█ •█▌ ▐█▐▌·
// ▐█ ▌▐▌▐█·▄█▀▀█ ▄█ ▀█▄▐█·██ ▄▄▐█▀▀█▄▄█▀▀█ ▐█▐ ▐▌▐▀▀▀
// ██ ██▌▐█▌▐█ ▪▐▌▐█▄▪▐█▐█▌▐███▌██▄▪▐█▐█ ▪▐▌██▐ █▌▐█▄▄▌
// ▀▀  █▪▀▀▀ ▀  ▀ ·▀▀▀▀ ▀▀▀·▀▀▀ ·▀▀▀▀  ▀  ▀ ▀▀  █▪ ▀▀▀
//      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.mbEnums;
import engine.gameManager.BuildingManager;
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.parent;
        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(mbEnums.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()) {

            subGuildList = new ArrayList<>();

            subGuildList.addAll(formerGuild.getSubGuildList());

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

        Building tol = null;

        // 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(mbEnums.BuildingGroup.BANESTONE))
                continue;

            // TOL is processed after all other structures in the city zone

            if (cityBuilding.getBlueprint().getBuildingGroup().equals(mbEnums.BuildingGroup.TOL)) {
                tol = cityBuilding;
                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(mbEnums.ProtectionState.NONE);

            // Destroy all remaining city assets

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

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

        // Destroy the tol

        if (tol != null)
            BuildingManager.setRank(tol, -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().zoneName + " uuid:" + city.getObjectUUID() + "has been destroyed!");
    }
}