package com.infinityraider.boatifull.boatlinking;

import com.google.common.primitives.Ints;
import com.infinityraider.boatifull.network.MessageRequestBoatSync;
import com.infinityraider.boatifull.reference.Names;
import com.infinityraider.infinitylib.network.NetworkWrapper;
import net.minecraft.entity.item.EntityBoat;
import net.minecraft.nbt.NBTTagCompound;

import java.util.*;

public class BoatId implements IBoatId {
    private static int largestId;
    private static final Set<Integer> FREE_IDS = new HashSet<>();
    private static final Map<Integer, EntityBoat> BOATS = new HashMap<>();

    /** The boat owning this property */
    private EntityBoat owner;

    /** The persistent id for this boat */
    private int id = -1;

    @Override
    public IBoatId setBoat(EntityBoat boat) {
        this.owner = boat;
        if(!boat.getEntityWorld().isRemote) {
            this.id = getNextId();
            BOATS.put(this.getId(), this.getBoat());
        } else {
            NetworkWrapper.getInstance().sendToServer(new MessageRequestBoatSync(this.owner));
        }
        return this;
    }

    @Override
    public EntityBoat getBoat() {
        return this.owner;
    }

    @Override
    public int getId() {
        return id;
    }

    @Override
    public NBTTagCompound writeToNBT() {
        NBTTagCompound tag = new NBTTagCompound();
        tag.setInteger(Names.NBT.ID, this.getId());
        tag.setInteger(Names.NBT.LEADER, largestId);
        tag.setIntArray(Names.NBT.OWNER, Ints.toArray(FREE_IDS));
        return tag;
    }

    @Override
    public void readFromNBT(NBTTagCompound tag) {
        this.id = tag.getInteger(Names.NBT.ID);
        largestId = tag.getInteger(Names.NBT.LEADER);
        int[] freeIds = tag.getIntArray(Names.NBT.OWNER);
        FREE_IDS.clear();
        for(int id : freeIds) {
            FREE_IDS.add(id);
        }
        BOATS.put(this.getId(), this.getBoat());
    }

    private static int getNextId() {
        int id;
        if(FREE_IDS.isEmpty()) {
            id = largestId + 1;
            largestId = id;
        } else {
            Iterator<Integer> iterator = FREE_IDS.iterator();
            id = iterator.next();
            FREE_IDS.remove(id);
        }
        return id;
    }

    public static EntityBoat getBoatFromId(int id) {
        return BOATS.get(id);
    }

    public static void onBoatRemoved(EntityBoat boat) {
        if(boat != null && !boat.getEntityWorld().isRemote) {
            FREE_IDS.add(BoatIdProvider.getBoatId(boat));
        }
    }
}

@@ -450,16 +450,21 @@
 argestId
+ = -1
 ;%0A    pr
@@ -792,32 +792,69 @@
 ityBoat boat) %7B%0A
+        if(this.owner == null) %7B%0A    
         this.own
@@ -872,18 +872,23 @@
         
+    
 if
+ 
 (!boat.g
@@ -919,32 +919,36 @@
 ) %7B%0A            
+   
+ 
 this.id = getNex
@@ -950,24 +950,28 @@
 etNextId();%0A
+    
             
@@ -1007,24 +1007,28 @@
 getBoat());%0A
+    
         %7D el
@@ -1044,16 +1044,20 @@
         
+    
 NetworkW
@@ -1127,24 +1127,38 @@
 is.owner));%0A
+            %7D%0A
         %7D%0A  

Make sure setBoatId() only works on the first call