package de.lessvoid.coregl;

import static org.lwjgl.opengl.GL11.GL_COLOR_BUFFER_BIT;
import static org.lwjgl.opengl.GL11.glClear;
import static org.lwjgl.opengl.GL11.glClearColor;

import java.nio.FloatBuffer;

import de.lessvoid.textureatlas.TextureAtlasGenerator;
import de.lessvoid.textureatlas.TextureAtlasGenerator.Result;
import de.lessvoid.textureatlas.TextureAtlasGeneratorException;

/**
 * This uses de.lessvoid.textureatlas.TextureAtlasGenerator while rendering individual CoreTextures into a
 * CoreRenderToTexture target.
 *
 * @author void
 */
public class CoreTextureAtlasGenerator {
  private CoreRenderToTexture renderToTexture;
  private CoreVAO vao;
  private CoreVBO vbo;
  private TextureAtlasGenerator generator;
  private CoreShader shader;

  public CoreTextureAtlasGenerator(final int width, final int height) {
    renderToTexture = new CoreRenderToTexture(width, height);

    shader = CoreShader.newShaderWithVertexAttributes("aVertex", "aUV");
    shader.vertexShader("de/lessvoid/coregl/plain-texture.vs");
    shader.fragmentShader("de/lessvoid/coregl/plain-texture.fs");
    shader.link();
    shader.activate();
    shader.setUniformi("uTexture", 0);
    shader.setUniformMatrix4f("uMvp", CoreMatrixFactory.createOrtho(0, width, 0, height));

    vao = new CoreVAO();
    vao.bind();

    vbo = CoreVBO.createStreamVBO(new float[4*4]);
    vbo.bind();

    vao.enableVertexAttributef(0, 2, 4, 0);
    vao.enableVertexAttributef(1, 2, 4, 2);

    renderToTexture.on();
    glClearColor(0.2f, 0.2f, 0.2f, 1.f);
    glClear(GL_COLOR_BUFFER_BIT);

    generator = new TextureAtlasGenerator(width, height);
  }

  public boolean addImage(final CoreTexture2D texture, final String name, final int padding) {
    try {
      Result result = generator.addImage(texture.getWidth(), texture.getHeight(), name, padding);
      put(texture, result.getX(), result.getY());
      return true;
    } catch (TextureAtlasGeneratorException e) {
      return false;
    }
  }

  public CoreRenderToTexture getDone() {
    renderToTexture.off();
    return renderToTexture;
  }

  private void put(final CoreTexture2D source, final int x, final int y) {
    FloatBuffer buffer = vbo.getBuffer();
    buffer.put(x);
    buffer.put(y);
    buffer.put(0.0f);
    buffer.put(0.0f);

    buffer.put(x);
    buffer.put(y + source.getHeight());
    buffer.put(0.0f);
    buffer.put(1.0f);

    buffer.put(x + source.getWidth());
    buffer.put(y);
    buffer.put(1.0f);
    buffer.put(0.0f);

    buffer.put(x + source.getWidth());
    buffer.put(y + source.getHeight());
    buffer.put(1.0f);
    buffer.put(1.0f);
    buffer.rewind();
    vbo.sendData();

    CoreRender.renderTriangleStrip(4);
  }
}

@@ -1181,99 +1181,8 @@
  0);
-%0A    shader.setUniformMatrix4f(%22uMvp%22, CoreMatrixFactory.createOrtho(0, width, 0, height));
 %0A%0A  
@@ -1478,16 +1478,61 @@
 ER_BIT);
+%0A    renderToTexture.off();%0A    vao.unbind();
 %0A%0A    ge
@@ -2112,24 +2112,224 @@
 al int y) %7B%0A
+    shader.activate();%0A    shader.setUniformMatrix4f(%22uMvp%22, CoreMatrixFactory.createOrtho(0, renderToTexture.getWidth(), 0, renderToTexture.getHeight()));%0A%0A    vao.bind();%0A    renderToTexture.on();%0A%0A
     FloatBuf
@@ -2809,24 +2809,24 @@
 endData();%0A%0A
-
     CoreRend
@@ -2852,14 +2852,59 @@
 rip(4);%0A
+    vao.unbind();%0A    renderToTexture.off();%0A
   %7D%0A%7D%0A

make put() operation independenly of current state