/*
* This flie is aimed to :
* 1.create picture shader
* 2.load pictures to GPU
* 3.use picture-program to draw 2D View
*/
#include "PlanView.h"
#ifndef STANDALONE
#include <utils/opengl/include/app_gl_egl_utils.h>
#endif

#define MODULE_NAME "AVM_PlanView"
#define AVM_DEBUG_SWITCH   1
#include "Avm_log.h"


static const char *vshader_plan = {
    "precision highp float;"
    "attribute vec2     plan_position;"
    "attribute vec2     plan_uv;"

    "varying   vec2     plan_outUV;"

    "void main()"
    "{"
    "    gl_Position =   vec4(plan_position.x, plan_position.y, 0.0, 1.0);"
    "    plan_outUV  =   vec2(1.0-plan_uv.x, plan_uv.y);"
    "}"
};

static const char *fshader_plan = {
#ifndef STANDALONE
    " #extension GL_OES_EGL_image_external : require \n"
#endif
    "precision highp float;"

#ifndef STANDALONE
    " uniform samplerExternalOES plan_texture;\n "
#else
    " uniform sampler2D plan_texture;\n "
#endif

    "varying  vec2   plan_outUV;"

    "void main()"
    "{"
//	"	plan_outUV.x = 1.0 - plan_outUV.x;"
    "    vec4 texcolor;\n"
    "   texcolor   =   texture2D(plan_texture, plan_outUV);"
    "   gl_FragColor = vec4(texcolor.zyxw);"
    "}"
};


#define ATTR_POSITION_PLAN    "plan_position"
#define ATTR_UV_PLAN          "plan_uv"

UndistGPUData *g_pstUndistGPUData = NULL;
UndistLRGPUData *g_stUndistLRGPUData = NULL;

static ThreeMosaicGPUData *g_stThreeMosaicGPUData = NULL
;
static BirdviewGPUData *g_stBirdviewGPUData = NULL;

static GLuint programPlan = 0;
static GLuint vsPlan_position2 = 100;
static GLuint vsPlan_uv2 = 100;


void esInitProgram_Plan()
{
    GLuint hdVerShader = 0;
    GLuint hdFrgShader = 0;
    GLuint hdPlanAttrib[2] = {0,0};

    esApplyAttribHandle(2, hdPlanAttrib);
    vsPlan_position2 = hdPlanAttrib[0];
    vsPlan_uv2 = hdPlanAttrib[1];

    esLoadShader(&vshader_plan, &fshader_plan, &hdVerShader, &hdFrgShader);
    programPlan = glCreateProgram();
    glAttachShader(programPlan, hdVerShader);
    glAttachShader(programPlan, hdFrgShader);
    glBindAttribLocation(programPlan, vsPlan_position2, ATTR_POSITION_PLAN);
    glBindAttribLocation(programPlan, vsPlan_uv2, ATTR_UV_PLAN);
    glLinkProgram(programPlan);
}

void GenerateUndist(OVSBasicInfo pOVSBasicInfo, UChar **dataUndist)
{

}

void GenerateUndist_LR(OVSBasicInfo pOVSBasicInfo, UChar **dataUndist_LR)
{

}

void GenerateThreeMosaic(OVSBasicInfo pOVSBasicInfo, UChar **dataThreeMosaic)
{

}

void GenerateBirdView(OVSBasicInfo pOVSBasicInfo, UChar **dataBirdView)
{

}


#define ENABLE_UNDIST_LR_VIEW   1
#define ENABLE_THREEMOSAIC_VIEW   1
#define ENABLE_LDW_VIEW   1

void LoadLutsFiles(char *dirLuts, OVSBasicInfo pOVSBasicInfo)
{
    int datasize = 0;

    do
    {
        if (NULL == g_pstUndistGPUData)
        {
            g_pstUndistGPUData = (UndistGPUData *)malloc(sizeof(UndistGPUData));
        }
        datasize = LoadFile(dirLuts, LUTS_UNDIST, (UChar **)&g_pstUndistGPUData, sizeof(UndistGPUData));
        if (datasize != sizeof(UndistGPUData))
        {
            GenerateUndist(pOVSBasicInfo, (UChar **)&g_pstUndistGPUData);
        }

#if ENABLE_UNDIST_LR_VIEW
        if (NULL == g_stUndistLRGPUData)
        {
            g_stUndistLRGPUData = (UndistLRGPUData *)malloc(sizeof(UndistLRGPUData));
        }
        datasize = LoadFile(dirLuts, LUTS_UNDIST_LR, (UChar **)&g_stUndistLRGPUData, sizeof(UndistLRGPUData));
        if (datasize != sizeof(UndistLRGPUData))
        {
            GenerateUndist_LR(pOVSBasicInfo, (UChar **)&g_stUndistLRGPUData);
        }
#endif

#if ENABLE_THREEMOSAIC_VIEW
        if (NULL == g_stThreeMosaicGPUData)
        {
            g_stThreeMosaicGPUData = (ThreeMosaicGPUData *)malloc(sizeof(ThreeMosaicGPUData));
        }
        datasize = LoadFile(dirLuts, LUTS_THREEMOSAIC, (UChar **)&g_stThreeMosaicGPUData, sizeof(ThreeMosaicGPUData));
        if (datasize != sizeof(ThreeMosaicGPUData))
        {
            GenerateThreeMosaic(pOVSBasicInfo, (UChar **)&g_stThreeMosaicGPUData);
        }
#endif

#if ENABLE_LDW_VIEW
        if (NULL == g_stBirdviewGPUData)
        {
            g_stBirdviewGPUData = (BirdviewGPUData *)malloc(sizeof(BirdviewGPUData));
        }
        datasize = LoadFile(dirLuts, LUTS_LDWVIEW, (UChar **)&g_stBirdviewGPUData, sizeof(BirdviewGPUData));
        if (datasize != sizeof(BirdviewGPUData))
        {
            GenerateBirdView(pOVSBasicInfo, (UChar **)&g_stBirdviewGPUData);
        }
#endif

    } while(0);

}


/*
*为外部模块提供静态轨迹线坐标数据，此设计目的是为了减少模块间的依赖性。但实际效果不佳
*/
void GetStaticTracks(float *staticTracks, float *staticLRTracks)
{
    if (NULL != staticTracks)
    {
        memcpy(staticTracks, g_pstUndistGPUData->Ltrack, 20*sizeof(float));
    }

    if (NULL != staticLRTracks)
    {
        memcpy(staticLRTracks, g_stUndistLRGPUData->Ltrack, 20*sizeof(float));
    }

}

bool PlanInit(ConfigFile FilePath, OVSBasicInfo pOVSBasicInfo)
{
    bool ret = FALSE;
    int datasize = 0;

    do
    {
        esInitProgram_Plan();

        LoadLutsFiles(FilePath.lutsPath, pOVSBasicInfo);

        ret = TRUE;
    } while(0);

    return ret;
}


void GetCoords(float *inVer, float *inTex, float *outVer, float *outTex, int ViewWidth, int floor)
{
    int k,i;

    for(k=0,i=0; k<ViewWidth*2; k+=2,i+=4)
    {
        *(outVer+i+0)= inVer[k+ViewWidth*2*floor];
        *(outVer+i+1)= inVer[k+1+ViewWidth*2*floor];
        *(outVer+i+2)= inVer[k+ViewWidth*2*(floor+1)];
        *(outVer+i+3)= inVer[k+1+ViewWidth*2*(floor+1)];

        *(outTex+i+0)= 1.0 - inTex[k+ViewWidth*2*floor];
        *(outTex+i+1)= 1.0 - inTex[k+1+ViewWidth*2*floor];
        *(outTex+i+2)= 1.0 - inTex[k+ViewWidth*2*(floor+1)];
        *(outTex+i+3)= 1.0 - inTex[k+1+ViewWidth*2*(floor+1)];
    }
}


/*绘制矫正图:前、后、左、右、前左右、后左右、前180、后180*/
void PlaneUndistRender(GLuint undistTexID, int viewWidth, int viewHeight, float *VerCoords, float *TexCoords)

{
    int t;

    do
    {
        GLfloat *Ver = (GLfloat *)malloc(viewWidth*4*sizeof(float));
        GLfloat *Tex = (GLfloat *)malloc(viewWidth*4*sizeof(float));

        glUseProgram(programPlan);
        glEnableVertexAttribArray(vsPlan_position2);
        glEnableVertexAttribArray(vsPlan_uv2);

        glUniform1i(glGetUniformLocation(programPlan, "plan_texture"), 0);
        glActiveTexture(GL_TEXTURE0);
#ifndef STANDALONE
        glBindTexture(GL_TEXTURE_EXTERNAL_OES, undistTexID);
#else
        glBindTexture(GL_TEXTURE_2D, undistTexID);
#endif

        for(t = 0; t < viewHeight-1; t++)
        {
            GetCoords(VerCoords, TexCoords, Ver, Tex, viewWidth, t);
            glVertexAttribPointer(vsPlan_position2, 2, GL_FLOAT, GL_FALSE, 0, Ver);
            glVertexAttribPointer(vsPlan_uv2, 2, GL_FLOAT, GL_FALSE, 0, Tex);
            glDrawArrays(GL_TRIANGLE_STRIP,0,viewWidth*2);
        }

#ifndef STANDALONE
        glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
#else
        glBindTexture(GL_TEXTURE_2D, 0);
#endif
        glDisableVertexAttribArray(vsPlan_position2);
        glDisableVertexAttribArray(vsPlan_uv2);
        glUseProgram(0);
        free(Ver);
        Ver = NULL;
        free(Tex);
        Tex = NULL;
    }while(0);
}

void PlaneBirdViewRender ()
{

}

/*
*Render Undist 2D View:前、后、左、右、前两侧、后两侧、前广角、后广角
*/
void PlaneUndistView(avmViewState avmWhitchView, GLuint *texid_Uds)
{
    switch (avmWhitchView)
    {
        case AVM_DISPLAY_STATE_CORRECT_FRONT:
            PlaneUndistRender(texid_Uds[2], g_pstUndistGPUData->iWNumber, g_pstUndistGPUData->iHNumber, g_pstUndistGPUData->VerAll, g_pstUndistGPUData->FrontTexAll);
            break;
        case AVM_DISPLAY_STATE_CORRECT_REAR:
            PlaneUndistRender(texid_Uds[3], g_pstUndistGPUData->iWNumber, g_pstUndistGPUData->iHNumber, g_pstUndistGPUData->VerAll, g_pstUndistGPUData->RearTexAll);
            break;
        case AVM_DISPLAY_STATE_CORRECT_LEFT:
            PlaneUndistRender(texid_Uds[0], g_pstUndistGPUData->iWNumber, g_pstUndistGPUData->iHNumber, g_pstUndistGPUData->VerAll, g_pstUndistGPUData->LeftTexAll);
            break;
        case AVM_DISPLAY_STATE_CORRECT_RIGHT:
            PlaneUndistRender(texid_Uds[1], g_pstUndistGPUData->iWNumber, g_pstUndistGPUData->iHNumber, g_pstUndistGPUData->VerAll, g_pstUndistGPUData->RightTexAll);
            break;
        case AVM_DISPLAY_STATE_CORRECT_LR_FRONT:
            PlaneUndistRender(texid_Uds[0], g_stUndistLRGPUData->iWNumber, g_stUndistLRGPUData->iHNumber, g_stUndistLRGPUData->LVerAll, g_stUndistLRGPUData->LTexAll);
            PlaneUndistRender(texid_Uds[1], g_stUndistLRGPUData->iWNumber, g_stUndistLRGPUData->iHNumber, g_stUndistLRGPUData->RVerAll, g_stUndistLRGPUData->RTexAll);
            break;
        case AVM_DISPLAY_STATE_CORRECT_LR_REAR:
            PlaneUndistRender(texid_Uds[0], g_stUndistLRGPUData->iWNumber, g_stUndistLRGPUData->iHNumber, g_stUndistLRGPUData->BLVerAll, g_stUndistLRGPUData->BLTexAll);
            PlaneUndistRender(texid_Uds[1], g_stUndistLRGPUData->iWNumber, g_stUndistLRGPUData->iHNumber, g_stUndistLRGPUData->BRVerAll, g_stUndistLRGPUData->BRTexAll);
            break;
        case AVM_DISPLAY_STATE_CORRECT_180_FRONT:
            PlaneUndistRender(texid_Uds[2], g_stThreeMosaicGPUData->iWNumber_F, g_stThreeMosaicGPUData->iHNumber_F, g_stThreeMosaicGPUData->VerAll_F, g_stThreeMosaicGPUData->FrontTexAll);
            break;
        case AVM_DISPLAY_STATE_CORRECT_180_REAR:
            PlaneUndistRender(texid_Uds[3], g_stThreeMosaicGPUData->iWNumber_R, g_stThreeMosaicGPUData->iHNumber_R, g_stThreeMosaicGPUData->VerAll_R, g_stThreeMosaicGPUData->RearTexAll);
            break;
        default:
            /* draw undist front view */
            PlaneUndistRender(texid_Uds[2], g_pstUndistGPUData->iWNumber, g_pstUndistGPUData->iHNumber, g_pstUndistGPUData->VerAll, g_pstUndistGPUData->FrontTexAll);
            break;
    }

    AVM_GL_CHECK("Render Undist View");
}


/*绘制相机标定时的原图, 支持混合*/
void PlaneOriginalRender(GLuint planTexID, int numPoints, float *VerCoords, float *TexCoords, bool isBlend)
{
    glUseProgram(programPlan);
    glEnableVertexAttribArray(vsPlan_position2);
    glEnableVertexAttribArray(vsPlan_uv2);
    glUniform1i(glGetUniformLocation(programPlan, "plan_texture"), 0);
    glActiveTexture(GL_TEXTURE0);
#ifndef STANDALONE
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, planTexID);
#else
    glBindTexture(GL_TEXTURE_2D, planTexID);
#endif

    if (1 == isBlend)
    {
        glDepthMask(GL_FALSE);
        glEnable(GL_BLEND);
    }
    glVertexAttribPointer(vsPlan_position2, 2, GL_FLOAT, GL_FALSE, 0, VerCoords);
    glVertexAttribPointer(vsPlan_uv2, 2, GL_FLOAT, GL_FALSE, 0, TexCoords);
    glDrawArrays(GL_TRIANGLE_STRIP,0,numPoints);
    if (1 == isBlend)
    {
        glDepthMask(GL_TRUE);
        glDisable(GL_BLEND);
    }
#ifndef STANDALONE
    glBindTexture(GL_TEXTURE_EXTERNAL_OES, 0);
#else
    glBindTexture(GL_TEXTURE_2D, 0);
#endif
    glDisableVertexAttribArray(vsPlan_position2);
    glDisableVertexAttribArray(vsPlan_uv2);
    glUseProgram(0);

}



/*
*绘制2D视图下用到的提示图标
*/
void PlanePicRender ()
{

}


#if 0
void SpliterRender()
{
    PlaneOriginalRender();
}
#endif




