package codechicken.lib.render;

import codechicken.lib.render.SpriteSheetManager.SpriteSheet;
import codechicken.lib.render.TextureUtils.IIconSelfRegister;
import cpw.mods.fml.relauncher.Side;
import cpw.mods.fml.relauncher.SideOnly;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.texture.IIconRegister;
import net.minecraft.client.renderer.texture.TextureAtlasSprite;
import net.minecraft.client.renderer.texture.TextureMap;
import net.minecraft.client.renderer.texture.TextureUtil;
import net.minecraft.client.resources.IResourceManager;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.util.ResourceLocation;

import java.awt.image.BufferedImage;
import java.util.ArrayList;

@SideOnly(Side.CLIENT)
public class TextureSpecial extends TextureAtlasSprite implements IIconSelfRegister {
    //sprite sheet fields
    private int spriteIndex;
    private SpriteSheet spriteSheet;

    //textureFX fields
    private TextureFX textureFX;

    private int blankSize = -1;
    private ArrayList<TextureDataHolder> baseTextures;

    private boolean selfRegister;
    public int atlasIndex;

    protected TextureSpecial(String par1) {
        super(par1);
    }

    public TextureSpecial addTexture(TextureDataHolder t) {
        if (baseTextures == null)
            baseTextures = new ArrayList<TextureDataHolder>();
        baseTextures.add(t);
        return this;
    }

    public TextureSpecial baseFromSheet(SpriteSheet spriteSheet, int spriteIndex) {
        this.spriteSheet = spriteSheet;
        this.spriteIndex = spriteIndex;
        return this;
    }

    public TextureSpecial addTextureFX(TextureFX fx) {
        textureFX = fx;
        return this;
    }

    @Override
    public void initSprite(int sheetWidth, int sheetHeight, int originX, int originY, boolean rotated) {
        super.initSprite(sheetWidth, sheetHeight, originX, originY, rotated);
        if (textureFX != null)
            textureFX.onTextureDimensionsUpdate(width, height);
    }

    @Override
    public void updateAnimation() {
        if (textureFX != null) {
            textureFX.update();
            if (textureFX.changed())
                TextureUtil.uploadTextureMipmap(new int[][]{textureFX.imageData}, width, height, originX, originY, false, false);
        }
    }

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

    public void addFrame(int[] data) {
        GameSettings settings = Minecraft.getMinecraft().gameSettings;
        BufferedImage[] images = new BufferedImage[settings.mipmapLevels+1];
        images[0] = new BufferedImage(width, height, BufferedImage.TYPE_INT_ARGB);
        images[0].setRGB(0, 0, width, height, data, 0, width);

        super.loadSprite(images, null, settings.anisotropicFiltering > 1);
    }

    @Override
    public boolean load(IResourceManager manager, ResourceLocation location) {
        if (baseTextures != null) {
            for (TextureDataHolder tex : baseTextures) {
                width = tex.width;
                height = tex.height;
                addFrame(tex.data);
            }
        }

        if (spriteSheet != null) {
            TextureDataHolder tex = spriteSheet.createSprite(spriteIndex);
            width = tex.width;
            height = tex.height;
            addFrame(tex.data);
        }

        if (blankSize > 0) {
            width = height = blankSize;
            addFrame(new int[blankSize * blankSize]);
        }

        if (framesTextureData.isEmpty())
            throw new RuntimeException("No base frame for texture: " + getIconName());

        return false;
    }

    @Override
    public boolean hasAnimationMetadata() {
        return textureFX != null || super.hasAnimationMetadata();
    }

    @Override
    public int getFrameCount() {
        if (textureFX != null)
            return 1;

        return super.getFrameCount();
    }

    public TextureSpecial blank(int size) {
        blankSize = size;
        return this;
    }

    public TextureSpecial selfRegister() {
        selfRegister = true;
        TextureUtils.addIconRegistrar(this);
        return this;
    }

    @Override
    public void registerIcons(IIconRegister register) {
        if (selfRegister)
            ((TextureMap) register).setTextureEntry(getIconName(), this);
    }

    @Override
    public int atlasIndex() {
        return atlasIndex;
    }
}

@@ -982,16 +982,46 @@
 xtureFX;
+%0A    private int mipmapLevels;
 %0A%0A    pr
@@ -2199,16 +2199,18 @@
 anged())
+ %7B
 %0A       
@@ -2222,131 +2222,473 @@
     
-TextureUtil.uploadTextureMipmap(new int%5B%5D%5B%5D%7BtextureFX.imageData%7D, width, height, originX, originY, false, false);%0A        %7D
+int%5B%5D%5B%5D mipmaps = new int%5BmipmapLevels + 1%5D%5B%5D;%0A                mipmaps%5B0%5D = textureFX.imageData;%0A                mipmaps = TextureUtil.generateMipmapData(mipmapLevels, width, mipmaps);%0A                TextureUtil.uploadTextureMipmap(mipmaps, width, height, originX, originY, false, false);%0A            %7D%0A        %7D%0A    %7D%0A%0A    @Override%0A    public void generateMipmaps(int p_147963_1_) %7B%0A        super.generateMipmaps(p_147963_1_);%0A        mipmapLevels = p_147963_1_;
 %0A   

Add mipmaps to animated TextureFX