/*
 * This file is a part of the SteamWar software.
 *
 * Copyright (C) 2020  SteamWar.de-Serverteam
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU Affero General Public License for more details.
 *
 * You should have received a copy of the GNU Affero General Public License
 * along with this program.  If not, see <https://www.gnu.org/licenses/>.
 */

package de.steamwar.bausystem.region.dynamic;

import com.sk89q.worldedit.EditSession;
import com.sk89q.worldedit.WorldEdit;
import com.sk89q.worldedit.bukkit.BukkitAdapter;
import com.sk89q.worldedit.regions.CuboidRegion;
import com.sk89q.worldedit.world.block.BlockTypes;
import de.steamwar.bausystem.region.DynamicRegionSystem;
import de.steamwar.bausystem.region.Point;
import de.steamwar.bausystem.region.Region;
import de.steamwar.bausystem.region.RegionBackups;
import lombok.Getter;
import lombok.NonNull;
import org.bukkit.Bukkit;

import java.util.UUID;
import java.util.stream.Collectors;

public abstract class DynamicRegion implements Region {

    @Getter
    protected final UUID ID;
    protected final int minX;
    protected final int minZ;

    @Getter
    protected final RegionBackups backups;

    protected DynamicRegion(int minX, int minZ) {
        this.ID = UUID.randomUUID();
        this.minX = minX;
        this.minZ = minZ;
        backups = RegionDataRepository.getBackups(this);
        RegionDataRepository.saveRegion(this);
        DynamicRegionSystem.INSTANCE.add(this);
    }

    protected DynamicRegion(RegionConstructorData regionConstructorData) {
        this.ID = regionConstructorData.uuid;
        this.minX = regionConstructorData.minX;
        this.minZ = regionConstructorData.minZ;
        backups = RegionDataRepository.getBackups(this);
        RegionDataRepository.saveRegion(this);
        DynamicRegionSystem.INSTANCE.add(this);
    }

    public RegionConstructorData getRegionConstructorData() {
        return new RegionConstructorData.RegionConstructorDataBuilder()
                .regionClass(this.getClass().getSimpleName())
                .uuid(ID)
                .minX(minX)
                .minZ(minZ)
                .build();
    }

    public abstract void update(DynamicRegion updateFrom);

    public abstract void setFlags(DefaultFlagStorage flags);

    @Override
    public abstract @NonNull DefaultFlagStorage getFlags();

    public void delete() {
        if (getType().isCannotDelete()) return;
        DynamicRegionSystem.INSTANCE.delete(this);
        RegionDataRepository.deleteRegion(this);

        Point minPoint = getArea().getMinPoint(false);
        Point maxPoint = getArea().getMaxPoint(false);

        EditSession editSession = WorldEdit.getInstance()
                .newEditSessionBuilder()
                .world(BukkitAdapter.adapt(Bukkit.getWorlds().get(0)))
                .checkMemory(false)
                .allowedRegionsEverywhere()
                .limitUnlimited()
                .changeSetNull()
                .build();
        editSession.setBlocks((com.sk89q.worldedit.regions.Region) new CuboidRegion(minPoint.toBlockVector3(), maxPoint.toBlockVector3()), BlockTypes.AIR.getDefaultState());
        editSession.close();

        DynamicRegionSystem.INSTANCE.getNeighbours(this).collect(Collectors.toList())
                .forEach(region -> region.update(this));
    }
}
