package com.example.opengles3;

import android.content.Context;
import android.content.ContextWrapper;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.drawable.Drawable;
import android.media.Image;
import android.opengl.GLES30;
import android.opengl.GLUtils;
import android.util.Log;

import com.example.rgprojekt.R;

import java.io.File;
import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

public class Kocka {
    private FloatBuffer vertexBuffer;
    float a = 0.5f;
    private int lokacijaMatrice;
    private int lokacijaBoje;
    float vrhovi[] = {-0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f,
            -0.5f, -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f,

            0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f,
            0.5f, -0.5f, 0.5f, 0.5f, 0.5f, -0.5f, 0.5f, 0.5f, 0.5f,

            0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f,
            0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f, -0.5f,

            -0.5f, -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f, 0.5f,
            -0.5f, -0.5f, -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, 0.5f, -0.5f,

            -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f,
            -0.5f, 0.5f, 0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f,

            -0.5f, -0.5f, 0.5f, -0.5f, -0.5f, -0.5f, 0.5f, -0.5f, -0.5f,
            -0.5f, -0.5f, 0.5f, 0.5f, -0.5f, -0.5f, 0.5f, -0.5f, 0.5f}; //donja strana za TRIANGLES
    private float color[] = new float[] {0.0f, 0.6f, 1, 1};
    private float color2[] = new float[] {1.0f, 0.0f, 1, 1};
    private float color3[] = new float[] {0.5f, 0.6f, 0, 1};
    private float color4[] = new float[] {1f, 1f, 0.5f, 1};
    private float color5[] = new float[] {1f, 0.1f, 0.2f, 1};
    private float color6[] = new float[] {1f, 1f, 1f, 1};
    private final String vertexShaderCode =
            "#version 300 es\n" +
                    "in vec4 vPosition;"+
                    "in vec4 vColor;"+
                    "out vec4 fColor;"+
                    "in vec2 a_texture;\n" +
                    "out vec2 v_texture;"+
                    "uniform mat4 matrica;"+
                    "void main()"+
                    "{"+
                    "    v_texture = a_texture;\n"+
                    "    gl_Position = matrica * vPosition;"+
                    "    fColor = vColor;"+
                    "}";
    private final String fragmentShaderCode =
            "#version 300 es\n" +
                    "precision mediump float;"+
                    "in vec4 fColor;"+
                    "out vec4 finalColor;"+
                    "uniform sampler2D u_slika;\n" +
                    "in vec2 v_texture;\n"+
                    "void main()"+
                    "{"+
                    //"    finalColor = fColor;"+
                    "    finalColor = vec4(0.4 * fColor.xyz + 0.6*texture(u_slika, v_texture).xyz , 1);"+
                    "}";





    /** Store our model data in a float buffer. */
    private FloatBuffer mCubeTextureCoordinates;
    /** This will be used to pass in the texture. */
    private int mTextureUniformHandle;
    /** This will be used to pass in model texture coordinate information. */
    private int mTextureCoordinateHandle;
    /** Size of the texture coordinate data in elements. */
    private final int mTextureCoordinateDataSize = 2;
    /** This is a handle to our texture data. */
    private int mTextureDataHandle;

    final float[] cubeTextureCoordinateData =
            {
                    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,

                    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,

                    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,

                    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,

                    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f,

                    0.0f, 0.0f, 1.0f, 0.0f, 1.0f, 1.0f,
                    0.0f, 0.0f, 1.0f, 1.0f, 0.0f, 1.0f
            };



    private int shaderProgram;
    public static int loadShader(int type, String shaderCode){
        int shader = GLES30.glCreateShader(type);
        GLES30.glShaderSource(shader, shaderCode);
        GLES30.glCompileShader(shader);
        return shader;
    }

    public Kocka(Bitmap _bitmap){
        mTextureDataHandle = loadTexture(_bitmap);
        ByteBuffer bb2 = ByteBuffer.allocateDirect(cubeTextureCoordinateData.length * 4);
        bb2.order(ByteOrder.nativeOrder());
        mCubeTextureCoordinates = bb2.asFloatBuffer();
        mCubeTextureCoordinates.put(cubeTextureCoordinateData);
        mCubeTextureCoordinates.position(0);


        ByteBuffer bb = ByteBuffer.allocateDirect(vrhovi.length * 4);
        bb.order(ByteOrder.nativeOrder());
        vertexBuffer = bb.asFloatBuffer();
        vertexBuffer.put(vrhovi);
        vertexBuffer.position(0);
        int vertexShader = loadShader(GLES30.GL_VERTEX_SHADER, vertexShaderCode);
        int fragmentShader = loadShader(GLES30.GL_FRAGMENT_SHADER, fragmentShaderCode);
        shaderProgram = GLES30.glCreateProgram();
        GLES30.glAttachShader(shaderProgram, vertexShader);
        GLES30.glAttachShader(shaderProgram, fragmentShader);

        // Bind vPosition to attribute 0
        GLES30.glBindAttribLocation(shaderProgram, 0, "vPosition");
        GLES30.glLinkProgram(shaderProgram);
    }
    public static int loadTexture(Bitmap _bitmap)
    {
        final int[] textureHandle = new int[1];

        GLES30.glGenTextures(1, textureHandle, 0);

        if (textureHandle[0] != 0)
        {
            final BitmapFactory.Options options = new BitmapFactory.Options();
            options.inScaled = false;   // No pre-scaling

            // Read in the resource
            final Bitmap bitmap = _bitmap;

            // Bind to the texture in OpenGL
            GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, textureHandle[0]);

            // Set filtering
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MIN_FILTER, GLES30.GL_NEAREST);
            GLES30.glTexParameteri(GLES30.GL_TEXTURE_2D, GLES30.GL_TEXTURE_MAG_FILTER, GLES30.GL_NEAREST);

            // Load the bitmap into the bound texture.
            GLUtils.texImage2D(GLES30.GL_TEXTURE_2D, 0, bitmap, 0);

            // Recycle the bitmap, since its data has been loaded into OpenGL.
            bitmap.recycle();
        }

        if (textureHandle[0] == 0)
        {
            throw new RuntimeException("Error loading texture.");
        }

        return textureHandle[0];
    }
    public void draw(float[] matrica/*, Bitmap bitmap*/) {
        mTextureCoordinateHandle = GLES30.glGetAttribLocation(shaderProgram, "a_texture");
        mTextureUniformHandle = GLES30.glGetUniformLocation(shaderProgram, "u_slika");
        // Set the active texture unit to texture unit 0.
        GLES30.glActiveTexture(GLES30.GL_TEXTURE0);
        // Bind the texture to this unit.
        GLES30.glBindTexture(GLES30.GL_TEXTURE_2D, mTextureDataHandle);
        // Tell the texture uniform sampler to use this texture in the shader by binding to texture unit 0.

        GLES30.glUniform1i(mTextureUniformHandle, 0);

        // Pass in the texture coordinate information
        mCubeTextureCoordinates.position(0);
        GLES30.glVertexAttribPointer(mTextureCoordinateHandle, mTextureCoordinateDataSize, GLES30.GL_FLOAT, false,
                0, mCubeTextureCoordinates);

        GLES30.glEnableVertexAttribArray(mTextureCoordinateHandle);


        GLES30.glUseProgram(shaderProgram);

        lokacijaMatrice = GLES30.glGetUniformLocation(shaderProgram, "matrica");
        lokacijaBoje = GLES30.glGetAttribLocation(shaderProgram, "vColor");

        GLES30.glUniformMatrix4fv(lokacijaMatrice, 1, false, matrica, 0);

        int VERTEX_POS_INDX = 0;
        vertexBuffer.position(VERTEX_POS_INDX);

        GLES30.glVertexAttribPointer(VERTEX_POS_INDX, 3, GLES30.GL_FLOAT,
                false, 0, vertexBuffer);
        GLES30.glEnableVertexAttribArray(VERTEX_POS_INDX);

        //CRTANJE KOCKE
        int startPos =0;
        int verticesPerface = 6;

        //front face
        GLES30.glVertexAttrib3fv(lokacijaBoje, color, 0);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface);
        startPos += verticesPerface;

        //back face
        GLES30.glVertexAttrib3fv(lokacijaBoje, color2, 0);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, startPos, verticesPerface);
        startPos += verticesPerface;

        //left face
        GLES30.glVertexAttrib3fv(lokacijaBoje, color3, 0);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface);
        startPos += verticesPerface;

        //right face
        GLES30.glVertexAttrib3fv(lokacijaBoje, color4, 0);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface);
        startPos += verticesPerface;

        //top face
        GLES30.glVertexAttrib3fv(lokacijaBoje, color5, 0);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface);
        startPos += verticesPerface;

        //bottom face
        GLES30.glVertexAttrib3fv(lokacijaBoje, color6, 0);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES,startPos,verticesPerface);

    }
}
