// 
// Decompiled by Procyon v0.6.0
// 

package com.hypixel.hytale.builtin.hytalegenerator.datastructures.compression;

import javax.annotation.Nonnull;

public class Compressor
{
    private final int MIN_RUN = 7;
    
    @Nonnull
    public <T> CompressedArray<T> compressOnReference(@Nonnull final T[] in) {
        int currentRun = 0;
        int resultIndex = 0;
        Object runObj = null;
        final Object[] result = new Object[in.length];
        for (int i = 0; i < result.length; ++i) {
            if (in[i] != runObj && currentRun >= 7) {
                result[resultIndex] = new Run(runObj, currentRun);
                currentRun = 0;
                ++resultIndex;
                runObj = in[i];
            }
            else if (in[i] != runObj && currentRun < 7) {
                while (currentRun > 0) {
                    result[resultIndex] = runObj;
                    ++resultIndex;
                    --currentRun;
                }
                currentRun = 0;
                runObj = in[i];
            }
            else {
                ++currentRun;
            }
        }
        if (currentRun >= 7) {
            result[resultIndex] = new Run(runObj, currentRun);
        }
        else {
            while (currentRun > 0) {
                result[resultIndex] = runObj;
                ++resultIndex;
                --currentRun;
            }
        }
        final Object[] trimmedResult = new Object[resultIndex];
        System.arraycopy(result, 0, trimmedResult, 0, trimmedResult.length);
        return new CompressedArray<T>(trimmedResult, in.length);
    }
    
    @Nonnull
    public <T> T[] decompress(@Nonnull final CompressedArray<T> compressedArray) {
        int caIndex = 0;
        int runIndex = 0;
        int outIndex = 0;
        final Object[] ca = compressedArray.data;
        final Object[] out = new Object[compressedArray.initialLength];
        while (caIndex < ca.length) {
            if (ca[caIndex] instanceof Run) {
                Run run;
                for (run = (Run)ca[caIndex], runIndex = 0; runIndex < run.length; ++runIndex) {
                    out[outIndex++] = run.obj;
                }
            }
            else {
                out[outIndex++] = ca[caIndex];
            }
            ++caIndex;
        }
        return (T[])out;
    }
    
    public static class Run
    {
        Object obj;
        int length;
        
        private Run(final Object obj, final int length) {
            this.obj = obj;
            this.length = length;
        }
    }
    
    public static class CompressedArray<T>
    {
        private final Object[] data;
        private final int initialLength;
        
        private CompressedArray(final Object[] data, final int initialLength) {
            this.data = data;
            this.initialLength = initialLength;
        }
    }
}
