package speiger.src.coreengine.rendering.textures.simple;

import java.io.IOException;
import java.nio.ByteBuffer;

import org.lwjgl.opengl.GL11;
import org.lwjgl.stb.STBImage;
import org.lwjgl.system.MemoryUtil;

import speiger.src.coreengine.assets.AssetLocation;
import speiger.src.coreengine.assets.base.IAsset;
import speiger.src.coreengine.assets.base.IAssetProvider;
import speiger.src.coreengine.assets.parsers.NativeMemoryParser;
import speiger.src.coreengine.rendering.textures.base.BaseTexture;
import speiger.src.coreengine.rendering.textures.base.TextureMetadata;
import speiger.src.coreengine.rendering.utils.GLFunctions;
import speiger.src.coreengine.rendering.utils.values.GLDataType;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureFormat;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureParameter;
import speiger.src.coreengine.rendering.utils.values.textures.GLTextureValue;

public class SimpleTexture extends BaseTexture {
	public static final TextureMetadata DEFAULT_DATA = TextureMetadata.builder()
						.externalFormat(GLTextureFormat.RGBA).internalFormat(GLTextureFormat.RGBAI).dataFormat(GLDataType.UNSIGNED_BYTE).mipmapping(false)
						.arguement(GLTextureParameter.MIN_FILTER, GLTextureValue.NEAREST).arguement(GLTextureParameter.MAG_FILTER, GLTextureValue.NEAREST)
						.arguement(GLTextureParameter.WRAP_S, GLTextureValue.CLAMP_TO_EDGE).arguement(GLTextureParameter.WRAP_T, GLTextureValue.CLAMP_TO_EDGE).build();
	AssetLocation location;
	TextureMetadata metadata;
	int width;
	int height;
	
	public SimpleTexture(AssetLocation location, TextureMetadata metadata) {
		this.location = location;
		this.metadata = metadata;
		track();
	}
	
	@Override
	public void load(IAssetProvider provider) {
		long address = 0L;
		int channel = GLTextureFormat.stbComponents(GL11.GL_RGBA);
		try(IAsset asset = provider.getAsset(location)) {
			ByteBuffer buffer = asset.custom(NativeMemoryParser.INSTANCE);
			int[] width = new int[1];
			int[] height = new int[1];
			int[] fileChannels = new int[1];
			address = STBImage.nstbi_load_from_memory(MemoryUtil.memAddress(buffer), buffer.remaining(), width, height, fileChannels, channel);
			MemoryUtil.memFree(buffer);
			if(address == 0) {
				throw new IllegalArgumentException("Couldn't load texture ["+location+"]");
			}
			this.width = width[0];
			this.height = height[0];
			if(channel == 0) channel = fileChannels[0];
		}
		catch(IOException e) {
			e.printStackTrace(); 
		}
		if(address == 0L) return;
		createTexture();
		metadata.applyArguments(id());
		GLFunctions.upload2DImage(id(), 0, metadata, width, height, 0, address);
		if(metadata.generateMipMappings()) GLFunctions.generateMipMaps(textureType());
		STBImage.nstbi_image_free(address);
	}
	
	@Override
	public int width() {
		return width;
	}
	
	@Override
	public int height() {
		return height;
	}
}
