package aeronicamc.mods.mxtune.caps.stages;

import aeronicamc.mods.mxtune.network.PacketDispatcher;
import aeronicamc.mods.mxtune.network.messages.StageAreaSyncMessage;
import net.minecraft.nbt.CompoundNBT;
import net.minecraft.nbt.INBT;
import net.minecraft.nbt.ListNBT;
import net.minecraft.nbt.NBTDynamicOps;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import javax.annotation.Nullable;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.WeakReference;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

public class ServerStageAreas implements IServerStageAreas
{
    private static final Logger LOGGER = LogManager.getLogger(ServerStageAreas.class);
    private WeakReference<World> levelRef;
    private final List<StageAreaData> stageAreas = new CopyOnWriteArrayList<>();

    private int someInt;

    ServerStageAreas() { /* NOP */ }

    ServerStageAreas(World level)
    {
        this();
        ReferenceQueue<World> worldReferenceQueue = new ReferenceQueue<>();
        this.levelRef = new WeakReference<>(level, worldReferenceQueue);
    }

    StageAreaData genTest1() {
        return new StageAreaData(
                                 new BlockPos(173,70,-441),
                                 new BlockPos(177,72,-445),
                                 new BlockPos(176,70,-441),
                                 new BlockPos(173,70,-441),
                                 "Stage#: 01",
                                 UUID.randomUUID());
    }

    StageAreaData genTest2() {
        return new StageAreaData(
                new BlockPos(169,73,-446),
                new BlockPos(164,69,-451),
                new BlockPos(167,69,-448),
                new BlockPos(166,69,-450),
                "Stage#: 02",
                UUID.randomUUID());
    }

    @Override
    public void test()
    {

        stageAreas.add(genTest1());
        stageAreas.add(genTest2());
        sync();
    }

    @Override
    public List<StageAreaData> getStageAreas()
    {
        return stageAreas;
    }

    @Override
    public int getInt()
    {
        return someInt;
    }

    @Override
    public void setInt(Integer someInt)
    {
        this.someInt = someInt;
        sync();
    }

    public void sync()
    {
        World level = levelRef.get();
        if (level != null && !level.isClientSide())
            {
                PacketDispatcher.sendToDimension(new StageAreaSyncMessage(serializeNBT()), level.dimension());
                LOGGER.debug("sync: someInt {}, stageAreas {}", this.someInt, this.stageAreas.size());
            }
    }

    @Override
    public INBT serializeNBT()
    {
        final CompoundNBT compoundNBT = new CompoundNBT();
        ListNBT listnbt = new ListNBT();
        stageAreas.forEach(stageArea -> NBTDynamicOps.INSTANCE.withEncoder(StageAreaData.CODEC)
                .apply(stageArea).result().ifPresent(listnbt::add));

        compoundNBT.put("stageAreas", listnbt);
        compoundNBT.putInt("someInt", getInt());
        return compoundNBT;
    }

    @Override
    public void deserializeNBT(@Nullable INBT nbt)
    {
        CompoundNBT cNbt = ((CompoundNBT) nbt);
        if (cNbt != null && cNbt.contains("stageAreas"))
        {
            ListNBT listnbt = cNbt.getList("stageAreas", Constants.NBT.TAG_COMPOUND);
            stageAreas.clear();
            listnbt.forEach(stageAreaNBT -> NBTDynamicOps.INSTANCE.withParser(StageAreaData.CODEC)
                    .apply(stageAreaNBT).result().ifPresent(stageAreas::add));

            setInt(cNbt.getInt("someInt"));
        }
    }
}

@@ -1286,23 +1286,30 @@
 reaData 
-gen
+stageArea
 Test
+0
 1() %7B%0A  
@@ -1340,33 +1340,16 @@
 eaData(%0A
-                 
         
@@ -1399,33 +1399,16 @@
         
-           
-      
 new Bloc
@@ -1442,33 +1442,16 @@
         
-        
-         
 new Bloc
@@ -1485,33 +1485,16 @@
         
-     
-            
 new Bloc
@@ -1532,56 +1532,22 @@
     
-                 %22Stage#: 01%22,%0A                 
+%22Stage#: 01%22,%0A
     
@@ -1603,23 +1603,30 @@
 reaData 
-gen
+stageArea
 Test
+0
 2() %7B%0A  
@@ -1945,17 +1945,16 @@
 )%0A    %7B%0A
-%0A
         
@@ -1968,23 +1968,30 @@
 eas.add(
-gen
+stageArea
 Test
+0
 1());%0A  
@@ -2015,15 +2015,22 @@
 add(
-gen
+stageArea
 Test
+0
 2())
@@ -2791,26 +2791,19 @@
 undNBT c
-ompoundNBT
+Nbt
  = new C
@@ -3028,34 +3028,27 @@
 ;%0A%0A        c
-ompoundNBT
+Nbt
 .put(%22stageA
@@ -3073,26 +3073,19 @@
        c
-ompoundNBT
+Nbt
 .putInt(
@@ -3122,26 +3122,19 @@
 return c
-ompoundNBT
+Nbt
 ;%0A    %7D%0A

Improve variable and method names. Cleanup.