package speiger.src.coreengine.rendering.texturesOld.base;

import java.awt.image.BufferedImage;
import java.nio.ByteBuffer;

import org.lwjgl.glfw.GLFWImage;
import org.lwjgl.opengl.GL11;
import org.lwjgl.opengl.GL13;
import org.lwjgl.system.MemoryUtil;

import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.AssetManager;
import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.reloader.IReloadableResource;
import speiger.src.coreengine.assets.reloader.ResourceReloader;
import speiger.src.coreengine.rendering.utils.GLStateTracker;
import speiger.src.coreengine.rendering.utils.states.GLState;
import speiger.src.coreengine.utils.io.GameLog;
import speiger.src.coreengine.utils.io.GameLog.LogLevel;

public class TextureManager implements IReloadableResource
{
	public static final TextureManager INSTANCE = new TextureManager();
	public static final GLState TEXTURE = GLStateTracker.instance().addState(new GLState(GL11.GL_TEXTURE_2D, false));
	AssetManager manager;
	ResourceReloader reloader = new ResourceReloader();
	int[] textureBanks = new int[GL13.GL_TEXTURE31 - GL13.GL_TEXTURE0];
	int activeBank = 0;
	
	public void init(AssetManager manager)
	{
		this.manager = manager;
	}
	
	public ResourceReloader getReloader()
	{
		return reloader;
	}
	
	public void addTexture(ITexture texture)
	{
		if(texture != null)
		{
			reloader.addReloadableResource(texture);
		}
	}
	
	public void removeTexture(ITexture texture)
	{
		if(texture != null)
		{
			GL11.glDeleteTextures(texture.getTextureId());
			reloader.removeReloadableResource(texture);
		}
	}
	
	public void removeTexture(int id)
	{
		GL11.glDeleteTextures(id);
	}
	
	public static void bindTexture(int texture)
	{
		INSTANCE.setActiveTexture(texture);
	}
	
	public static void bindTexture(int texture, int bank)
	{
		INSTANCE.setActiveTexture(texture, bank);
	}
	
	public static void unbindTexture()
	{
		INSTANCE.setActiveTexture(0);
	}
	
	public void setActiveTexture(int texture)
	{
		if(textureBanks[activeBank] != texture)
		{
			textureBanks[activeBank] = texture;
			GL11.glBindTexture(GL11.GL_TEXTURE_2D, texture);
		}
	}
	
	public void setActiveTexture(int texture, int bank)
	{
		if(activeBank != bank)
		{
			activeBank = bank;
			GL13.glActiveTexture(GL13.GL_TEXTURE0 + activeBank);
		}
		bindTexture(texture);
	}
	
	@Override
	public void reload()
	{
		reloader.reloadResources();
	}
	
	@Override
	public void destroy()
	{
		reloader.deleteResources();
	}
	
	public AssetManager getManager()
	{
		return manager;
	}
	
	public static GLFWImage create(AssetLocation location)
	{
		try(IAsset asset = INSTANCE.manager.getAsset(location))
		{
			BufferedImage image = asset.texture();
			int width = image.getWidth();
			int height = image.getHeight();
			int[] pixelData = new int[width * height];
			image.getRGB(0, 0, width, height, pixelData, 0, width);
			ByteBuffer buffer = MemoryUtil.memAlloc(pixelData.length * 4);
			for(int y = 0;y<height;y++)
			{
				for(int x = 0;x<width;x++)
				{
					int pixel = pixelData[(y * width) + x];
					buffer.put((byte)((pixel >> 16) & 0xFF));
					buffer.put((byte)((pixel >> 8) & 0xFF));
					buffer.put((byte)(pixel & 0xFF));
					buffer.put((byte)((pixel >> 24) & 0xFF));
				}
			}
			GLFWImage glfw = GLFWImage.malloc();
			glfw.set(width, height, buffer);
			return glfw;
		}
		catch(Exception e)
		{
			GameLog.error("Couldn't Load Texture ["+location.toString()+"]", e, LogLevel.ERROR);
			return null;
		}
	}
}
