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.RegistryKey;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraftforge.fml.common.thread.EffectiveSide;
import org.apache.commons.lang3.RandomUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.UUID;

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

    int someInt;

    ServerStageAreas() { /* NOP */ }

    ServerStageAreas(RegistryKey<World> dimension)
    {
        this();
        this.dimension = dimension;
    }

    StageAreaData genTest() {
        return new StageAreaData(dimension,
                                 new BlockPos(173, 70, -441),
                                 new BlockPos(177 + RandomUtils.nextInt(1,5),72 + RandomUtils.nextInt(4, 10),-445 - RandomUtils.nextInt(3, 7)),
                                 new BlockPos(176,70,-441),
                                 new BlockPos(173,70,-441), "Stage#: " + RandomUtils.nextInt(), UUID.randomUUID());
    }

    @Override
    public void test()
    {
        stageAreas.add(genTest());
    }

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

    @Override
    public RegistryKey<World> getDimension()
    {
        return this.dimension;
    }

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

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

    public void sync()
    {
        if (EffectiveSide.get().isServer())
        {
            PacketDispatcher.sendToAll(new StageAreaSyncMessage(Objects.requireNonNull(serializeNBT())));
            LOGGER.debug("{someInt {}, stageAreas {}", this.someInt, this.stageAreas);
        } else {
            LOGGER.debug("{someInt {}, stageAreas {}", this.someInt, this.stageAreas);
        }
    }

    @Override
    public INBT serializeNBT()
    {
        final CompoundNBT compoundNBT = new CompoundNBT();
        ListNBT listnbt = new ListNBT();
        for(StageAreaData stageArea : stageAreas) {
            NBTDynamicOps.INSTANCE.withEncoder(StageAreaData.CODEC).apply(stageArea).result().ifPresent(p -> {
                listnbt.add(p.copy());
            });
        }
        compoundNBT.put("stageAreas", listnbt);

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

    @Override
    public void deserializeNBT(INBT nbt)
    {
        CompoundNBT compoundNBT = ((CompoundNBT) nbt);
        if (nbt != null)
        {
            if (compoundNBT.contains("stageAreas"))
            {
                ListNBT listnbt = compoundNBT.getList("stageAreas", 10);
                stageAreas.clear();
                for (INBT stageAreaNBT : listnbt)
                {
                    NBTDynamicOps.INSTANCE.withParser(StageAreaData.CODEC).apply(stageAreaNBT).result().ifPresent(stageAreaData -> stageAreas.add(stageAreaData));
                }
                setInt(compoundNBT.getInt("someInt"));
            }
        }
    }
}

@@ -420,16 +420,65 @@
 .World;%0A
+import net.minecraftforge.common.util.Constants;%0A
 import n
@@ -662,36 +662,8 @@
 r;%0A%0A
-import java.util.ArrayList;%0A
 impo
@@ -729,16 +729,66 @@
 il.UUID;
+%0Aimport java.util.concurrent.CopyOnWriteArrayList;
 %0A%0Apublic
@@ -933,16 +933,24 @@
 s);%0A    
+private 
 Registry
@@ -971,24 +971,38 @@
 ension;%0A    
+private final 
 List%3CStageAr
@@ -1026,16 +1026,27 @@
 s = new 
+CopyOnWrite
 ArrayLis
@@ -1057,16 +1057,24 @@
 );%0A%0A    
+private 
 int some
@@ -1731,32 +1731,80 @@
 id test()%0A    %7B%0A
+        genTest().getAreaAABB().inflate(0.002);%0A
         stageAre
@@ -2296,26 +2296,16 @@
 rver())%0A
-        %7B%0A
         
@@ -2406,116 +2406,9 @@
 ));%0A
-            LOGGER.debug(%22%7BsomeInt %7B%7D, stageAreas %7B%7D%22, this.someInt, this.stageAreas);%0A        %7D else %7B%0A    
+%0A
     
@@ -2486,26 +2486,16 @@
 Areas);%0A
-        %7D%0A
     %7D%0A%0A 
@@ -2656,21 +2656,17 @@
     
-for(S
+s
 tageArea
 Data
@@ -2665,50 +2665,30 @@
 Area
-Data stageArea : stageAreas) %7B%0A           
+s.forEach(stageArea -%3E
  NBT
@@ -2731,32 +2731,65 @@
 eAreaData.CODEC)
+%0A                                
 .apply(stageArea
@@ -2813,79 +2813,24 @@
 ent(
-p -%3E %7B%0A                
 listnbt
-.add(p.copy());%0A            %7D);%0A        %7D
+::add));%0A
 %0A   
@@ -2874,17 +2874,16 @@
 stnbt);%0A
-%0A
         
@@ -3243,18 +3243,42 @@
 Areas%22, 
-10
+Constants.NBT.TAG_COMPOUND
 );%0A     
@@ -3328,57 +3328,40 @@
     
-for (INBT stageAreaNBT : listnbt)%0A               
+listnbt.forEach( stageAreaNBT -%3E
  %7B%0A 
@@ -3433,16 +3433,45 @@
 a.CODEC)
+%0A                            
 .apply(s
@@ -3560,32 +3560,34 @@
                %7D
+);
 %0A               

Work on stages. lamda lamda . . .