package PMeditor;

import com.jogamp.common.util.IOUtil;
import com.jogamp.opengl.util.FPSAnimator;
import com.jogamp.opengl.util.texture.Texture;
import com.jogamp.opengl.util.texture.TextureCoords;
import com.jogamp.opengl.util.texture.TextureData;
import com.jogamp.opengl.util.texture.TextureIO;
import java.io.IOException;
import java.net.URLConnection;
import javax.media.opengl.DebugGL2;
import javax.media.opengl.GL2;
import javax.media.opengl.GLAutoDrawable;
import javax.media.opengl.GLCapabilities;
import javax.media.opengl.GLDrawableFactory;
import javax.media.opengl.GLEventListener;
import javax.media.opengl.GLException;
import javax.media.opengl.GLPbuffer;
import javax.media.opengl.GLProfile;

public final class RenderEngine implements GLEventListener {
    private static FPSAnimator animator=new FPSAnimator(25);
    private DatasProjet project;
    
    public RenderEngine(DatasProjet project) {
        this.project=project;
        if (!GLDrawableFactory.getFactory(new GLCapabilities(GLProfile.getGL2GL3()).getGLProfile()).canCreateGLPbuffer(null)) {
            System.out.println("GPU not compatible");
        }
        GLPbuffer pbuffer=GLDrawableFactory.getFactory(GLProfile.getGL2GL3())
                .createGLPbuffer(null, new GLCapabilities(GLProfile.getGL2GL3()), null, project.getWidth(), project.getHeight(), null);
        pbuffer.addGLEventListener(this);
        pbuffer.display();
    }
    
   @Override
   public void init(GLAutoDrawable drawable) {
        GL2 gl = drawable.getGL().getGL2();
      drawable.setGL(new DebugGL2(gl.getGL2()));    // remove
        gl.glClearColor(0.0f, 0.0f, 1.0f, 0.0f);
        gl.glDisable(GL2.GL_DEPTH_TEST);
        gl.glShadeModel(GL2.GL_SMOOTH);
        animator.start();
   }
 
   @Override
   public void reshape(GLAutoDrawable drawable, int x, int y, int width, int height) {
      GL2 gl = drawable.getGL().getGL2();
      gl.glViewport(0, 0, width, height);
      gl.glMatrixMode(GL2.GL_PROJECTION);
      gl.glLoadIdentity();
      gl.glOrtho(-width/2,width/2,-height/2,height/2, 0.1, 100);
      gl.glMatrixMode(GL2.GL_MODELVIEW);
      gl.glLoadIdentity();
   }
 
   @Override
   public void display(GLAutoDrawable drawable) {
       GL2 gl = drawable.getGL().getGL2();
       int[] result = new int[1];
       int fboID;
       int colorTexID;
       int depthTexID;
        gl.glGenFramebuffers(1,result,0);
        fboID=result[0];
        gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, fboID);
        gl.glGenTextures(1, result, 0);
        colorTexID=result[0];
        gl.glBindTexture(GL2.GL_TEXTURE_2D, colorTexID);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
        gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_RGBA8, project.getWidth(), project.getHeight(),
                                                    0, GL2.GL_RGBA, GL2.GL_UNSIGNED_BYTE, null);
        gl.glGenTextures(1, result, 0);
        depthTexID=result[0];
        gl.glBindTexture(GL2.GL_TEXTURE_2D, depthTexID);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MIN_FILTER, GL2.GL_NEAREST);
        gl.glTexParameteri(GL2.GL_TEXTURE_2D, GL2.GL_TEXTURE_MAG_FILTER, GL2.GL_NEAREST);
        gl.glTexImage2D(GL2.GL_TEXTURE_2D, 0, GL2.GL_DEPTH_COMPONENT32, project.getWidth(), project.getHeight(), 
                0, GL2.GL_DEPTH_COMPONENT, GL2.GL_UNSIGNED_INT, null);
        //Attach 2D texture to this FBO
        gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, GL2.GL_COLOR_ATTACHMENT0, GL2.GL_TEXTURE_2D, colorTexID, 0);
        gl.glFramebufferTexture2D(GL2.GL_FRAMEBUFFER, GL2.GL_DEPTH_ATTACHMENT, GL2.GL_TEXTURE_2D, depthTexID, 0);
        gl.glBindFramebuffer(GL2.GL_FRAMEBUFFER, 0);
        
        try{
            String layerPath=project.getLayerPath;
            URLConnection urlConn=IOUtil.getResource(layerPath, this.getClass().getClassLoader());
            TextureData texData = TextureIO.newTextureData(GLProfile.getGL2GL3(), urlConn.getInputStream(), 
                    false, layerPath.substring(layerPath.length()-3, layerPath.length()));
            Texture texture = TextureIO.newTexture(texData);

            gl.glPushAttrib(GL2.GL_TEXTURE_BIT);
            gl.glActiveTexture(GL2.GL_TEXTURE0);
            gl.glBindTexture(GL2.GL_TEXTURE_2D, colorTexID);
            texture.enable(gl);
            texture.bind(gl);
            TextureCoords tc = texture.getImageTexCoords();
            
            float ratio=(float)project.getWidth()/texture.getWidth();
            if((float)texture.getHeight()*ratio>project.getHeight()) {
                ratio=(float)project.getHeight()/texture.getHeight();}
            
            gl.glBegin(GL2.GL_QUADS);
            gl.glTexCoord2f(tc.right(), tc.top());
                gl.glVertex2f((float)project.getWidth()/2*ratio, (float)project.getHeight()/2*ratio);
            gl.glTexCoord2f(tc.right(), tc.bottom());
                gl.glVertex2f((float)project.getWidth()/2*ratio, (float)-project.getHeight()/2*ratio);
            gl.glTexCoord2f(tc.left(), tc.bottom());
                gl.glVertex2f((float)-project.getWidth()/2*ratio, (float)-project.getHeight()/2*ratio);
            gl.glTexCoord2f(tc.left(), tc.top());
                gl.glVertex2f((float)-project.getWidth()/2*ratio, (float)project.getHeight()/2*ratio);
            gl.glEnd(); 

            texture.disable(gl);
        gl.glBindTexture(GL2.GL_TEXTURE_2D, 0);
        gl.glPopAttrib();
        
        }catch (GLException|IOException exc) {
            System.out.println("Error in texture: "+exc.getMessage());
        }
         
        int fboStatus = gl.glCheckFramebufferStatus(GL2.GL_FRAMEBUFFER);
        if(fboStatus != GL2.GL_FRAMEBUFFER_COMPLETE) {
            System.out.println("GL_FRAMEBUFFER_COMPLETE_EXT failed, CANNOT use FBO: " + fboStatus);
        }
        else {
            System.out.println("Framebuffer created successfully");
            project.getLayer.setPvwTex(TextureIO.newTexture(colorTexID, GL2.GL_TEXTURE_2D, project.getWidth(), 
                    project.getHeight(), project.getWidth(), project.getHeight(), true));
            System.out.println("texture = "+project.getLayer.getPvwTex().getEstimatedMemorySize());
            //save file
        }
        gl.glDeleteFramebuffers(1,result,0);
   }
   
   @Override
   public void dispose(GLAutoDrawable drawable) { }
 
}