package twilightforest.client.texture;

import com.google.common.collect.ImmutableList;
import com.google.common.collect.Lists;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.util.ResourceLocation;
import twilightforest.TwilightForestMod;

import java.util.Collection;
import java.util.function.Function;

public class MoltenFieryTexture extends TextureAtlasSprite {
    private final ResourceLocation textureDependency;
    private float minimumValue;
    private float maximumValue;

    private static final GradientNode[] GRADIENT_MAP = {
            new GradientNode(0.0f, 0xFF_08_06_06),
            new GradientNode(0.2f, 0xFF_19_13_13),
            new GradientNode(0.7f, 0xFF_3C_23_23)
    };

    public MoltenFieryTexture(ResourceLocation textureDependency, ResourceLocation spriteName) {
        super(spriteName.toString());
        this.textureDependency = textureDependency;
    }

    @Override
    public boolean hasCustomLoader(IResourceManager manager, ResourceLocation location) {
        return true;
    }

    @Override
    public boolean load(IResourceManager manager, ResourceLocation location, Function<ResourceLocation, TextureAtlasSprite> textureGetter) {
        final TextureAtlasSprite sprite = textureGetter.apply(textureDependency);

        copyFrom(sprite);
        this.animationMetadata = sprite.animationMetadata;

        this.framesTextureData = Lists.newArrayList();

        int minimumValue = 255;
        int maximumValue = 0;

        for (int i = 0; i < sprite.getFrameCount(); i++) {
            final int[][] textureFrom = sprite.getFrameTextureData(i).clone();
            int [][] textureTo = new int[textureFrom.length][];

            for (int j = 0; j < textureFrom.length; j++) {
                textureTo[j] = new int[textureFrom[j].length];
                System.arraycopy(textureFrom[j], 0, textureTo[j], 0, textureFrom[j].length);
            }

            for (int pixel : textureTo[0]) {
                if ((pixel >> 24 & 0xFF) == 0) continue;

                minimumValue = Math.min(minimumValue, getPerceptualBrightness(pixel));
                maximumValue = Math.max(maximumValue, getPerceptualBrightness(pixel));
            }

            this.framesTextureData.add(i, textureTo);
        }

        if (minimumValue > maximumValue) {
            this.minimumValue = maximumValue / 255f;
            this.maximumValue = minimumValue / 255f;
        } else {
            this.minimumValue = minimumValue / 255f;
            this.maximumValue = maximumValue / 255f;
        }

        for (int i = 0; i < framesTextureData.size(); i++) {
            int [][] texture = this.framesTextureData.get(i);

            for (int l = 0; l < texture.length; l++) {
                for (int j = 0; j < texture[l].length; j++) {
                    texture[l][j] = GradientMappedTexture.getGradient(texture[l][j], GRADIENT_MAP, this.minimumValue, this.maximumValue);
                }
            }
        }

        TwilightForestMod.LOGGER.debug("Autogenerated {} from {}", this.getIconName(), this.textureDependency);

        return false;
    }

    @Override
    public Collection<ResourceLocation> getDependencies() {
        return ImmutableList.of(textureDependency);
    }

    // borrowed from Shadows of Physis
    // Thanks TTFTCUTS! :)
    private static int getPerceptualBrightness(int col) {
        return getPerceptualBrightness((col >> 16 & 0xFF) / 255.0, (col >> 8 & 0xFF) / 255.0, (col & 0xFF) / 255.0);
    }

    private static int getPerceptualBrightness(double r, double g, double b) {
        return (int) (Math.sqrt(0.241 * r * r + 0.691 * g * g + 0.068 * b * b) * 255);
    }
}
