/*
 * To change this license header, choose License Headers in Project Properties.
 * To change this template file, choose Tools | Templates
 * and open the template in the editor.
 */
package electrosphere.renderer.texture;

import electrosphere.main.Main;
import electrosphere.util.FileUtils;
import java.awt.Color;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.imageio.ImageIO;
import org.lwjgl.BufferUtils;
import static org.lwjgl.opengl.GL11.*;
import static org.lwjgl.opengl.GL14.*;
import static org.lwjgl.opengl.GL30.*;

/**
 *
 * @author amaterasu
 */
public class Texture {
    int texturePointer;
    int width;
    int height;
    boolean hasTransparency;
    String path = "";
    public Texture(){
        
    }
    public Texture(String path){
        this.path = path;
        //generate the texture object on gpu
        texturePointer = glGenTextures();
        //bind the new texture
        glBindTexture(GL_TEXTURE_2D, texturePointer);
        //how are we gonna wrap the texture??
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_MIRRORED_REPEAT);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_MIRRORED_REPEAT);
        //set the border color to black
        float borderColor[] = { 0.0f, 0.0f, 0.0f, 1.0f };
        glTexParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, borderColor);
        //set magnification and minification operation sampling strategies
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        //load the image here
        ByteBuffer data;
        width = 1;
        height = 1;
        try {
            BufferedImage image_data = ImageIO.read(FileUtils.getAssetFile(path));
            if (
                    image_data.getType() == BufferedImage.TYPE_3BYTE_BGR ||
                    image_data.getType() == BufferedImage.TYPE_INT_RGB
                    ){
                hasTransparency = false;
            } else if(
                    image_data.getType() == BufferedImage.TYPE_4BYTE_ABGR ||
                    image_data.getType() == BufferedImage.TYPE_INT_ARGB
                    ){
                hasTransparency = true;
            }
            width = image_data.getWidth();
            height = image_data.getHeight();
            if(hasTransparency){
                data = BufferUtils.createByteBuffer(width * height * 4);
            } else {
                data = BufferUtils.createByteBuffer(width * height * 3);
            }
            /*
            imgBuffer = BufferUtils.createByteBuffer(4 * dimX * dimY);
            for(int x = 0; x < dimX; x++){
                for(int y = 0; y < dimY; y++){
                    Color temp = new Color(image_data.getRGB(x, y));
                    data.put((byte)(temp.getRed());
                    data.put((byte)(temp.getGreen());
                    data.put((byte)(temp.getBlue());
                    data.put((byte)(temp.getAlpha());
                }
            }
            imgBuffer.flip();
            */
            for(int y = height - 1; y > -1; y--){
                for(int x = 0; x < width; x++){
                    Color temp = new Color(image_data.getRGB(x, y), true);
                    
                    data.put((byte)temp.getRed());
                    data.put((byte)temp.getGreen());
                    data.put((byte)temp.getBlue());
                    if(hasTransparency){
                        data.put((byte)temp.getAlpha());
                    }
//                    data[x * y * 3 + 0] = temp.getRed();
//                    data[x * y * 3 + 1] = temp.getGreen();
//                    data[x * y * 3 + 2] = temp.getBlue();
                }
            }
        } catch (IOException ex) {
            ex.printStackTrace();
            hasTransparency = false;
            data = BufferUtils.createByteBuffer(3);
            data.put((byte)0);
            data.put((byte)0);
            data.put((byte)0);
        }
        data.flip();
        //call if width != height so opengl figures out how to unpack it properly
        if(width != height){
            glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
        }
        //buffer the texture information
        if(hasTransparency){
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, data);
        } else {
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
        }
        glGenerateMipmap(GL_TEXTURE_2D);
        //OPTIONAL free the original image data now that it's on the gpu
        System.gc();
    }
    
    public void bind(){
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, texturePointer);
    }
    
    public void bind(int attrib_val){
        glActiveTexture(GL_TEXTURE0 + attrib_val);
        glBindTexture(GL_TEXTURE_2D, texturePointer);
    }
    
    public boolean isTransparent(){
        return hasTransparency;
    }
    
    public String getPath(){
        return path;
    }
    
    public int getTexturePointer(){
        return texturePointer;
    }
}
