package client.renderer.texture;

import static org.lwjgl.system.MemoryUtil.NULL;

import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.IntBuffer;

import javax.imageio.ImageIO;

import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL12;

import client.renderer.GlState;
import client.util.FileUtils;

public class TextureUtil
{
    private static final IntBuffer BUFFER = ByteBuffer.allocateDirect(4194304 << 2).order(ByteOrder.nativeOrder()).asIntBuffer();
    public static final DynamicTexture MISSING = new DynamicTexture(16, 16);
    public static final int[] MISSING_DATA = MISSING.getData();

    public static void uploadTexture(int[] data, int w, int h, int x, int y)
    {
        int i = 4194304 / w;
        GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
        int l;

        for (int j = 0; j < w * h; j += w * l)
        {
            int k = j / w;
            l = Math.min(i, h - k);
            int i1 = w * l;
            BUFFER.clear();
			BUFFER.put(data, j, i1);
			BUFFER.position(0).limit(i1);
            GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, x, y + k, w, l, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, BUFFER);
        }
    }

    public static int uploadImage(int id, BufferedImage img)
    {
        allocateTexture(id, img.getWidth(), img.getHeight());
        GlState.bindTexture(id);
		int w = img.getWidth();
		int h = img.getHeight();
		int k = 4194304 / w;
		int[] data = new int[k * w];
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MIN_FILTER, GL11.GL_NEAREST);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_MAG_FILTER, GL11.GL_NEAREST);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_S, GL11.GL_REPEAT);
		GL11.glTexParameteri(GL11.GL_TEXTURE_2D, GL11.GL_TEXTURE_WRAP_T, GL11.GL_REPEAT);
		
		for (int l = 0; l < w * h; l += w * k)
		{
		    int i1 = l / w;
		    int j1 = Math.min(k, h - i1);
		    int k1 = w * j1;
		    img.getRGB(0, i1, w, j1, data, 0, w);
		    BUFFER.clear();
			BUFFER.put(data, 0, k1);
			BUFFER.position(0).limit(k1);
		    GL11.glTexSubImage2D(GL11.GL_TEXTURE_2D, 0, 0, i1, w, j1, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, BUFFER);
		}
		return id;
    }

    public static void allocateTexture(int id, int width, int height)
    {
//        GlState.deleteTexture(id); //TODO: check needed
        GlState.bindTexture(id);
        GL11.nglTexImage2D(GL11.GL_TEXTURE_2D, 0, GL11.GL_RGBA, width, height, 0, GL12.GL_BGRA, GL12.GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
    }

    public static int[] readImageData(String loc) throws IOException
    {
        BufferedImage img = readImage(FileUtils.getResource(loc));
        int w = img.getWidth();
        int h = img.getHeight();
        int[] data = new int[w * h];
        img.getRGB(0, 0, w, h, data, 0, w);
        return data;
    }
    
    public static BufferedImage readImage(InputStream in) throws IOException
    {
        BufferedImage img;

        try
        {
            img = ImageIO.read(in);
        }
        finally
        {
            try {
				if(in != null) {
					in.close();
				}
			}
			catch(IOException e) {
			}
        }

        return img;
    }

    static
    {
        int i = -16777216;
        int j = -524040;
        int[] aint = new int[] { -524040, -524040, -524040, -524040, -524040, -524040, -524040, -524040};
        int[] aint1 = new int[] { -16777216, -16777216, -16777216, -16777216, -16777216, -16777216, -16777216, -16777216};
        int k = aint.length;

        for (int l = 0; l < 16; ++l)
        {
            System.arraycopy(l < k ? aint : aint1, 0, MISSING_DATA, 16 * l, k);
            System.arraycopy(l < k ? aint1 : aint, 0, MISSING_DATA, 16 * l + k, k);
        }

        MISSING.updateTexture();
    }
}
