package com.zivilon.cinder_loe.mixins;

import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
import lotr.common.world.genlayer.LOTRIntCache;
import com.zivilon.cinder_loe.util.Utilities;

import java.util.List;

@Mixin(LOTRIntCache.class)
public abstract class MixinLOTRIntCache {

    @Shadow(remap = false)
    private static LOTRIntCache SERVER;
    @Shadow(remap = false)
    private static LOTRIntCache CLIENT;
    @Shadow(remap = false)
    private int intCacheSize = 256;
    @Shadow(remap = false)
    private List<int[]> freeSmallArrays;
    @Shadow(remap = false)
    private List<int[]> inUseSmallArrays;
    @Shadow(remap = false)
    private List<int[]> freeLargeArrays;
    @Shadow(remap = false)
    private List<int[]> inUseLargeArrays;

    /**
    * @author Shinare
    * @reason Unsuccessfully trying to patch a crash bug
    */
    @Overwrite(remap = false)
    public int[] getIntArray(int size) {
        try {
            if (size <= 256) {
                if (this.freeSmallArrays.isEmpty()) {
                    int[] arrayOfInt1 = new int[256];
                    this.inUseSmallArrays.add(arrayOfInt1);
                    return cacheInts(arrayOfInt1);
                }
                int[] arrayOfInt = this.freeSmallArrays.remove(this.freeSmallArrays.size() - 1);
                this.inUseSmallArrays.add(arrayOfInt);
                return cacheInts(arrayOfInt);
            }
            if (size > this.intCacheSize) {
                this.intCacheSize = size;
                this.freeLargeArrays.clear();
                this.inUseLargeArrays.clear();
                int[] arrayOfInt = new int[this.intCacheSize];
                this.inUseLargeArrays.add(arrayOfInt);
                return cacheInts(arrayOfInt);
            }
            if (this.freeLargeArrays.isEmpty()) {
                int[] arrayOfInt = new int[this.intCacheSize];
                this.inUseLargeArrays.add(arrayOfInt);
                return cacheInts(arrayOfInt);
            }
            int[] ints = this.freeLargeArrays.remove(this.freeLargeArrays.size() - 1);
            this.inUseLargeArrays.add(ints);
            return cacheInts(ints);
        } catch (IndexOutOfBoundsException e) {
            System.err.println("Caught IndexOutOfBoundsException in getIntArray: " + e.getMessage());
            return new int[size];
        }
    }

    private int[] cacheInts(int[] ints) {
        Utilities.LOTRIntCache = ints;
        return ints;
    }
}
