package com.example.wilson.mymediacodecfpvplayer;


import android.opengl.GLES20;
import android.util.Log;

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

public class OpenGLHelper {
    public static int createProgram(String vertexSource, String fragmentSource) {
        int vertexShader = loadShader(GLES20.GL_VERTEX_SHADER, vertexSource);
        if (vertexShader == 0) {
            return 0;
        }
        int pixelShader = loadShader(GLES20.GL_FRAGMENT_SHADER, fragmentSource);
        if (pixelShader == 0) {
            return 0;
        }
        int program = GLES20.glCreateProgram();
        if (program != 0) {
            GLES20.glAttachShader(program, vertexShader);
            checkGlError("glAttachShader");
            GLES20.glAttachShader(program, pixelShader);
            checkGlError("glAttachShader");
            GLES20.glLinkProgram(program);
            int[] linkStatus = new int[1];
            GLES20.glGetProgramiv(program, GLES20.GL_LINK_STATUS, linkStatus, 0);
            if (linkStatus[0] != GLES20.GL_TRUE) {
                GLES20.glDeleteProgram(program);
                program = 0;
            }
        }
        return program;
    }

    public static void checkGlError(String op) {
        int error;
        while ((error = GLES20.glGetError()) != GLES20.GL_NO_ERROR) {
            throw new RuntimeException(op + ": glError " + error);
        }
    }
    public static int loadShader(int shaderType, String source) {
        int shader = GLES20.glCreateShader(shaderType);
        if (shader != 0) {
            GLES20.glShaderSource(shader, source);
            GLES20.glCompileShader(shader);
            int[] compiled = new int[1];
            GLES20.glGetShaderiv(shader, GLES20.GL_COMPILE_STATUS, compiled, 0);
            if (compiled[0] == 0) {
                GLES20.glDeleteShader(shader);
                shader = 0;
            }
        }
        return shader;
    }
    public static FloatBuffer getFloatBuffer(float[] floatBuffer){
        FloatBuffer bb = ByteBuffer.allocateDirect(
                floatBuffer.length*4) .order(ByteOrder.nativeOrder()).asFloatBuffer();
        bb.put(floatBuffer).position(0);
        return bb;
    }

    public static void makeRectangle(float[] array,int arrayOffset,float x,float y,float z,float height,float width,float r,float g,float b,float a){
        array[arrayOffset   ]=x;
        array[arrayOffset+ 1]=y;
        array[arrayOffset+ 2]=z;
        array[arrayOffset+ 3]=r;
        array[arrayOffset+ 4]=g;
        array[arrayOffset+ 5]=b;
        array[arrayOffset+ 6]=a;
        array[arrayOffset+ 7]=x+width;
        array[arrayOffset+ 8]=y;
        array[arrayOffset+ 9]=z;
        array[arrayOffset+10]=r;
        array[arrayOffset+11]=g;
        array[arrayOffset+12]=b;
        array[arrayOffset+13]=a;
        array[arrayOffset+14]=x+width;
        array[arrayOffset+15]=y-height;
        array[arrayOffset+16]=z;
        array[arrayOffset+17]=r;
        array[arrayOffset+18]=g;
        array[arrayOffset+19]=b;
        array[arrayOffset+20]=a;
        array[arrayOffset+21]=x;
        array[arrayOffset+22]=y;
        array[arrayOffset+23]=z;
        array[arrayOffset+24]=r;
        array[arrayOffset+25]=g;
        array[arrayOffset+26]=b;
        array[arrayOffset+27]=a;
        array[arrayOffset+28]=x+width;
        array[arrayOffset+29]=y-height;
        array[arrayOffset+30]=z;
        array[arrayOffset+31]=r;
        array[arrayOffset+32]=g;
        array[arrayOffset+33]=b;
        array[arrayOffset+34]=a;
        array[arrayOffset+35]=x;
        array[arrayOffset+36]=y-height;
        array[arrayOffset+37]=z;
        array[arrayOffset+38]=r;
        array[arrayOffset+39]=g;
        array[arrayOffset+40]=b;
        array[arrayOffset+41]=a;
    }
    public static void makeRectangle2(float[] array,int arrayOffset,float x,float y,float z,float height,float width,float xOff,float offset){
        array[arrayOffset   ]=x;
        array[arrayOffset+ 1]=y;
        array[arrayOffset+ 2]=z;
        array[arrayOffset+ 3]=xOff;
        array[arrayOffset+ 4]=0.0f;
        array[arrayOffset+ 5]=x+width;
        array[arrayOffset+ 6]=y;
        array[arrayOffset+ 7]=z;
        array[arrayOffset+ 8]=xOff+offset;
        array[arrayOffset+ 9]=0.0f;
        array[arrayOffset+10]=x+width;
        array[arrayOffset+11]=y-height;
        array[arrayOffset+12]=z;
        array[arrayOffset+13]=xOff+offset;
        array[arrayOffset+14]=1.0f;
        array[arrayOffset+15]=x;
        array[arrayOffset+16]=y;
        array[arrayOffset+17]=z;
        array[arrayOffset+18]=xOff;
        array[arrayOffset+19]=0.0f;
        array[arrayOffset+20]=x+width;
        array[arrayOffset+21]=y-height;
        array[arrayOffset+22]=z;
        array[arrayOffset+23]=xOff+offset;
        array[arrayOffset+24]=1.0f;
        array[arrayOffset+25]=x;
        array[arrayOffset+26]=y-height;
        array[arrayOffset+27]=z;
        array[arrayOffset+28]=xOff;
        array[arrayOffset+29]=1.0f;
    }
    public static void makeRectangle3(float[] array,int arrayOffset,
                                      float x,float y,float z,
                                      float x2, float y2,float z2,
                                      float x3,float y3, float z3,
                                      float x4,float y4,float z4,
                                      float xOff,float offset){
        array[arrayOffset   ]=x;
        array[arrayOffset+ 1]=y;
        array[arrayOffset+ 2]=z;
        array[arrayOffset+ 3]=xOff;
        array[arrayOffset+ 4]=0.0f;
        array[arrayOffset+ 5]=x2;
        array[arrayOffset+ 6]=y2;
        array[arrayOffset+ 7]=z2;
        array[arrayOffset+ 8]=xOff+offset;
        array[arrayOffset+ 9]=0.0f;
        array[arrayOffset+10]=x3;
        array[arrayOffset+11]=y3;
        array[arrayOffset+12]=z3;
        array[arrayOffset+13]=xOff+offset;
        array[arrayOffset+14]=1.0f;
        array[arrayOffset+15]=x;
        array[arrayOffset+16]=y;
        array[arrayOffset+17]=z;
        array[arrayOffset+18]=xOff;
        array[arrayOffset+19]=0.0f;
        array[arrayOffset+20]=x3;
        array[arrayOffset+21]=y3;
        array[arrayOffset+22]=z3;
        array[arrayOffset+23]=xOff+offset;
        array[arrayOffset+24]=1.0f;
        array[arrayOffset+25]=x4;
        array[arrayOffset+26]=y4;
        array[arrayOffset+27]=z4;
        array[arrayOffset+28]=xOff;
        array[arrayOffset+29]=1.0f;
    }
    public static void makeRoundVideoCanvas(float[] array,int arrayOffset,int steppSize,float height,float width){
        //4 rectangles
        int count=0;
        float r=(width/2);
        /*
        double distance_x=1-Math.cos(Math.toRadians((double)alpha_steppSize));
        distance_x=(distance_x*distance_x);
        double distance_z=Math.sin(Math.toRadians((double)alpha_steppSize));
        distance_z=(distance_z*distance_z);
        float texture_radius=(float)Math.sqrt(distance_x+distance_z);*/
        float alpha_steppSize=(180/steppSize);
        float texture_radius=1/(180/alpha_steppSize);
        for(int alpha=180;alpha>0;alpha-=alpha_steppSize){
            float x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4;
            x1=(float)(r*Math.cos(Math.toRadians((double)alpha)));
            y1=(height/2);
            z1=-(float)(r*Math.sin(Math.toRadians((double) alpha)));
            x2=(float)(r*Math.cos(Math.toRadians((double)alpha+alpha_steppSize)));
            y2=(height/2);
            z2=-(float)(r*Math.sin(Math.toRadians((double) alpha+alpha_steppSize)));
            x3=(float)(r*Math.cos(Math.toRadians((double)alpha+alpha_steppSize)));
            y3=-(height/2);
            z3=-(float)(r*Math.sin(Math.toRadians((double)alpha+alpha_steppSize)));
            x4=(float)(r*Math.cos(Math.toRadians((double)alpha)));
            y4=-(height/2);
            z4=-(float)(r*Math.sin(Math.toRadians((double) alpha)));
            makeRectangle3(array,arrayOffset+(count*5*6),x1,y1,z1,x2,y2,z2,x3,y3,z3,x4,y4,z4,count*texture_radius,texture_radius);
            count++;
        }
    }

    public static float[] getIcoSphereCoords(){
        float t = (float)((Math.sqrt(5) - 1)/2);
        float[][] icoshedronVertices = new float[][] {
                new float[] { -1,-t,0 },
                new float[] { 0,1,t },
                new float[] { 0,1,-t },
                new float[] { 1,t,0 },
                new float[] { 1,-t,0 },
                new float[] { 0,-1,-t },
                new float[] { 0,-1,t },
                new float[] { t,0,1 },
                new float[] { -t,0,1 },
                new float[] { t,0,-1 },
                new float[] { -t,0,-1 },
                new float[] { -1,t,0 },
        };
        for (float[] v : icoshedronVertices) {
            // Normalize the vertices to have unit length.
            float length = (float)Math.sqrt(v[0]*v[0]+v[1]*v[1]+v[2]*v[2]);
            v[0] /= length;
            v[1] /= length;
            v[2] /= length;
        }
        for(int i1=0;i1<12;i1++){
            for(int i2=0;i2<3;i2++){
                icoshedronVertices[i1][i2]=6*icoshedronVertices[i1][i2];
            }
        }
        int[][] icoshedronFaces = new int[][] {
                { 3, 7, 1 },
                { 4, 7, 3 },
                { 6, 7, 4 },
                { 8, 7, 6 },
                { 7, 8, 1 },
                { 9, 4, 3 },
                { 2, 9, 3 },
                { 2, 3, 1 },
                { 11, 2, 1 },
                { 10, 2, 11 },
                { 10, 9, 2 },
                { 9, 5, 4 },
                { 6, 4, 5 },
                { 0, 6, 5 },
                { 0, 11, 8 },
                { 11, 1, 8 },
                { 10, 0, 5 },
                { 10, 5, 9 },
                { 0, 8, 6 },
                { 0, 10, 11 },
        };
        float[] vertices=new float[20*15];
        for(int i=0;i<20;i++){
            int index=icoshedronFaces[i][0];
            //first Triangle with tex. coords
            vertices[(i*15)+0]=icoshedronVertices[index][0];
            vertices[(i*15)+1]=icoshedronVertices[index][1];
            vertices[(i*15)+2]=icoshedronVertices[index][2];
            vertices[(i*15)+3]=0.0f;
            vertices[(i*15)+4]=1.0f;
            index=icoshedronFaces[i][1];
            vertices[(i*15)+5]=icoshedronVertices[index][0];
            vertices[(i*15)+6]=icoshedronVertices[index][1];
            vertices[(i*15)+7]=icoshedronVertices[index][2];
            vertices[(i*15)+8]=0.0f;
            vertices[(i*15)+9]=0.0f;
            index=icoshedronFaces[i][2];
            vertices[(i*15)+10]=icoshedronVertices[index][0];
            vertices[(i*15)+11]=icoshedronVertices[index][1];
            vertices[(i*15)+12]=icoshedronVertices[index][2];
            vertices[(i*15)+13]=1.0f;
            vertices[(i*15)+14]=0.0f;
        }

        return vertices;
    }


}