package com.example.opengles3;

import android.opengl.GLES30;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;
import java.util.ArrayList;

public class Kugla {
    private FloatBuffer vertexBuffer;//plašt
    float a = 0.5f;
    private int lokacijaMatrice;
    private int lokacijaBoje;
    float vrhovi[];//plašt
    private static double DEG = Math.PI/180;
    private float color[] = new float[] {0.3f, 0.3f, 0.3f, 1};
    private final String vertexShaderCode =
            "#version 300 es\n" +
                    "      in vec4 a_position;\n" +
                    "      in vec4 v_boja;\n" +
                    "      out float f_boja;\n" +
                    "      uniform mat4 matrica;\n" +
                    "\n" +
                    "      void main() {\n" +
                    "        f_boja = abs(sin((a_position.x+a_position.z)*10.0f));\n" +
                    "        gl_Position = vec4(matrica * a_position); // primijeni matricu transformacije\n" +
                    "      }";
    private final String fragmentShaderCode =
            "#version 300 es\n" +
                    "      precision mediump float;\n" +
                    "      in float f_boja;\n" +
                    "      out vec4 bojaPiksela;\n" +
                    "\n" +
                    "      void main() {\n" +
                    "       float x = f_boja;"+
                    "        bojaPiksela = vec4(0.0f,0.0f,x, 1); // boja se postavlja preko flat varijable f_boja\n" +
                    "      }";
    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 Kugla(float radius, double step){
        ArrayList<Float> pos=new ArrayList<>();
        double dTheta = step * DEG;
        double dPhi = dTheta;
        int points = 0;

        for (double vAngle = 0; vAngle < Math.PI; vAngle = vAngle + step) { // vertical
            for (double hAngle = 0; hAngle < 2 * Math.PI; hAngle = hAngle + step) { // horizontal

                float x0 = (float) (radius * Math.sin(vAngle) * Math.cos(hAngle));
                float y0 = (float) (radius * Math.cos(vAngle));
                float z0 = (float) (radius * Math.sin(vAngle) * Math.sin(hAngle));

                float x1 = (float) (radius * Math.sin(vAngle) * Math.cos(hAngle + step));
                float y1 = (float) (radius * Math.cos(vAngle));
                float z1 = (float) (radius * Math.sin(vAngle) * Math.sin(hAngle + step));

                float x2 = (float) (radius * Math.sin(vAngle + step) * Math.cos(hAngle + step));
                float y2 = (float) (radius * Math.cos(vAngle + step));
                float z2 = (float) (radius * Math.sin(vAngle + step) * Math.sin(hAngle + step));

                float x3 = (float) (radius * Math.sin(vAngle + step) * Math.cos(hAngle));
                float y3 = (float) (radius * Math.cos(vAngle + step));
                float z3 = (float) (radius * Math.sin(vAngle + step) * Math.sin(hAngle));

                pos.add(x1);
                pos.add(y1);
                pos.add(z1);

                pos.add(x3);
                pos.add(y3);
                pos.add(z3);

                pos.add(x0);
                pos.add(y0);
                pos.add(z0);

                pos.add(x1);
                pos.add(y1);
                pos.add(z1);

                pos.add(x2);
                pos.add(y2);
                pos.add(z2);

                pos.add(x3);
                pos.add(y3);
                pos.add(z3);
            }

        }
        vrhovi = new float[pos.size()];    //All vertices
        for (int i=0;i<vrhovi.length;i++){
            vrhovi[i]=pos.get(i);
        }


        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, "a_position");
        GLES30.glLinkProgram(shaderProgram);

        int[] linkStatus = new int[1];
        GLES30.glGetProgramiv(shaderProgram, GLES30.GL_LINK_STATUS, linkStatus, 0);
        if (linkStatus[0] != GLES30.GL_TRUE) {
            GLES30.glDeleteProgram(shaderProgram);
            throw new RuntimeException("Could not link shader program: "
                    + GLES30.glGetProgramInfoLog(shaderProgram));
        }
    }

    public void draw(float[] matrica) {

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

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

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


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

        GLES30.glVertexAttrib3fv(lokacijaBoje, color, 0);
        GLES30.glDrawArrays(GLES30.GL_TRIANGLES, 0, vrhovi.length/3);

    }
}
