package client.renderer.texture;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.util.List;

import client.renderer.texture.TextureTicked.TextureCreator;
import common.collect.Lists;

public class Sprite
{
    private final String iconName;
    protected List<int[]> framesTextureData = Lists.<int[]>newArrayList();
    private int frameCount;
    private int frametime;
    protected boolean rotated;
    protected int originX;
    protected int originY;
    protected int width;
    protected int height;
    private float minU;
    private float maxU;
    private float minV;
    private float maxV;
    protected int frameCounter;
    protected int tickCounter;
    private TextureTicked tickedTexture;

    protected Sprite(String spriteName)
    {
        this.iconName = spriteName;
    }

    public void initSprite(int inX, int inY, int originInX, int originInY, boolean rotatedIn)
    {
        this.originX = originInX;
        this.originY = originInY;
        this.rotated = rotatedIn;
        float f = (float)(0.009999999776482582D / (double)inX);
        float f1 = (float)(0.009999999776482582D / (double)inY);
        this.minU = (float)originInX / (float)((double)inX) + f;
        this.maxU = (float)(originInX + this.width) / (float)((double)inX) - f;
        this.minV = (float)originInY / (float)inY + f1;
        this.maxV = (float)(originInY + this.height) / (float)inY - f1;
    }

    public void copyFrom(Sprite atlasSpirit)
    {
        this.originX = atlasSpirit.originX;
        this.originY = atlasSpirit.originY;
        this.width = atlasSpirit.width;
        this.height = atlasSpirit.height;
        this.rotated = atlasSpirit.rotated;
        this.minU = atlasSpirit.minU;
        this.maxU = atlasSpirit.maxU;
        this.minV = atlasSpirit.minV;
        this.maxV = atlasSpirit.maxV;
    }

    public int getOriginX()
    {
        return this.originX;
    }

    public int getOriginY()
    {
        return this.originY;
    }

    public int getIconWidth()
    {
        return this.width;
    }

    public int getIconHeight()
    {
        return this.height;
    }

    public float getMinU()
    {
        return this.minU;
    }

    public float getMaxU()
    {
        return this.maxU;
    }

    public float getInterpolatedU(double u)
    {
        float f = this.maxU - this.minU;
        return this.minU + f * (float)u / 16.0F;
    }

    public float getMinV()
    {
        return this.minV;
    }

    public float getMaxV()
    {
        return this.maxV;
    }

    public float getInterpolatedV(double v)
    {
        float f = this.maxV - this.minV;
        return this.minV + f * ((float)v / 16.0F);
    }

    public String getIconName()
    {
        return this.iconName;
    }

    public void updateAnimation()
    {
        ++this.tickCounter;
        
        if(this.tickedTexture != null) {
        	int[] data = this.framesTextureData.get(0);
        	this.tickedTexture.renderStep(data);
        	TextureUtil.uploadTexture(data, this.width, this.height, this.originX, this.originY);
        	return;
        }

        if (this.tickCounter >= this.frametime)
        {
            int i = this.frameCounter;
            int j = this.frameCount == 0 ? this.framesTextureData.size() : this.frameCount;
            this.frameCounter = (this.frameCounter + 1) % j;
            this.tickCounter = 0;
            int k = this.frameCounter;

            if (i != k && k >= 0 && k < this.framesTextureData.size())
            {
                TextureUtil.uploadTexture(this.framesTextureData.get(k), this.width, this.height, this.originX, this.originY);
            }
        }
    }

    public int[] getFrameTextureData(int index)
    {
        return this.framesTextureData.get(index);
    }

    public int getFrameCount()
    {
        return this.framesTextureData.size();
    }

    public void setIconWidth(int newWidth)
    {
        this.width = newWidth;
    }

    public void setIconHeight(int newHeight)
    {
        this.height = newHeight;
    }

    public void loadSprite(BufferedImage image, int frametime) throws IOException
    {
        this.resetSprite();
        int i = image.getWidth();
        int j = image.getHeight();
        this.width = i;
        this.height = j;
        int[] aint = new int[i * j];
        image.getRGB(0, 0, i, j, aint, 0, i);

        if (frametime == 0)
        {
            if (j != i)
            {
                throw new RuntimeException("Falsches Seitenverhältnis und keine Animation");
            }

            this.framesTextureData.add(aint);
        }
        else
        {
            int frames = j / i;
            int k1 = i;
            int l = i;
            this.height = this.width;

            for (int l1 = 0; l1 < frames; ++l1)
            {
                int[] aint2 = new int[k1 * l];
                System.arraycopy(aint, l1 * aint2.length, aint2, 0, aint2.length);
                this.framesTextureData.add(aint2);
            }

            this.frameCount = frames;
            this.frametime = frametime;
        }
    }
    
    public void loadSprite(TextureCreator tex)
    {
        this.resetSprite();
		this.tickedTexture = tex.create();
		this.height = this.width = this.tickedTexture.getSize();
    	int[] aint = new int[this.height * this.width];
		this.framesTextureData.add(aint);
		this.frameCount = 0;
        this.frametime = 1;
    }

    private void allocateFrameTextureData(int index)
    {
        if (this.framesTextureData.size() <= index)
        {
            for (int i = this.framesTextureData.size(); i <= index; ++i)
            {
                this.framesTextureData.add(null);
            }
        }
    }

    public void clearFramesTextureData()
    {
        this.framesTextureData.clear();
    }

    public boolean isAnimated()
    {
        return this.frametime != 0;
    }

    public void setFramesTextureData(List<int[]> newFramesTextureData)
    {
        this.framesTextureData = newFramesTextureData;
    }

    private void resetSprite()
    {
        this.frameCount = 0;
        this.frametime = 0;
        this.setFramesTextureData(Lists.<int[]>newArrayList());
        this.frameCounter = 0;
        this.tickCounter = 0;
    }
}
