/*
 * Copyright (C) 2011 The Android Open Source Project
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include <GLES/gl.h>
#include <GLES2/gl2.h>
#include <GLES/glext.h>

#include <rs_hal.h>
#include <rsContext.h>
#include <rsPath.h>

#include "rsdCore.h"
#include "rsdPath.h"
#include "rsdAllocation.h"
#include "rsdGL.h"
#include "rsdVertexArray.h"
#include "rsdShaderCache.h"

using namespace android;
using namespace android::renderscript;

class DrvPath {
protected:
    DrvPath();
public:
    virtual ~DrvPath();
    virtual void draw(Context *) = 0;
};

class DrvPathStatic : public DrvPath {
public:
    typedef struct {
        float x1, xc, x2;
        float y1, yc, y2;
    } segment_t;

    segment_t *mSegments;
    uint32_t mSegmentCount;

    DrvPathStatic(const Allocation *vtx, const Allocation *loops);
    virtual ~DrvPathStatic();

    virtual void draw(Context *);
};

class DrvPathDynamic : public DrvPath {
public:
    DrvPathDynamic();
    virtual ~DrvPathDynamic();
};

static void cleanup(const Context *rsc, const Path *m) {
    DrvPath *dp = (DrvPath *)m->mHal.drv;
    if (dp) {
        delete dp;
    }
}

bool rsdPathInitStatic(const Context *rsc, const Path *m,
                       const Allocation *vtx, const Allocation *loops) {
    DrvPathStatic *drv = NULL;
    cleanup(rsc, m);

    DrvPathStatic *dps = new DrvPathStatic(vtx, loops);
    //LOGE("init path m %p,  %p", m, dps);
    m->mHal.drv = dps;
    return dps != NULL;
}

bool rsdPathInitDynamic(const Context *rsc, const Path *m) {
    return false;
}


void rsdPathDraw(const Context *rsc, const Path *m) {
    //LOGE("render m=%p", m);

    DrvPath *drv = (DrvPath *)m->mHal.drv;
    if(drv) {
        //LOGE("render 2 drv=%p", drv);
        drv->draw((Context *)rsc);
    }
}

void rsdPathDestroy(const Context *rsc, const Path *m) {
    cleanup(rsc, m);
    m->mHal.drv = NULL;
}




DrvPath::DrvPath() {
}

DrvPath::~DrvPath() {
}

DrvPathStatic::DrvPathStatic(const Allocation *vtx, const Allocation *loops) {
    mSegmentCount = vtx->getType()->getDimX() / 3;
    mSegments = new segment_t[mSegmentCount];
/*
    const float *fin = (const float *)vtx->getPtr();
    for (uint32_t ct=0; ct < mSegmentCount; ct++) {
        segment_t *s = &mSegments[ct];
        s->x1 = fin[0];
        s->y1 = fin[1];

        s->xc = fin[2];
        s->yc = fin[3];

        s->x2 = fin[4];
        s->y2 = fin[5];
        fin += 6;
    }
    */
}

DrvPathStatic::~DrvPathStatic() {
}

void DrvPathStatic::draw(Context *rsc) {
    const static float color[24] = {
        1.f, 0.f, 0.f, 1.f,  0.5f, 0.f, 0.f, 1.f,
        1.f, 0.f, 0.f, 1.f,  0.5f, 0.f, 0.f, 1.f,
        1.f, 1.f, 1.f, 1.f,  1.f, 1.f, 1.f, 1.f};
    float vtx[12];

    //LOGE("draw");
    if (!rsc->setupCheck()) {
        return;
    }

    RsdHal *dc = (RsdHal *)rsc->mHal.drv;
    if (!dc->gl.shaderCache->setup(rsc)) {
        return;
    }

    RsdVertexArray::Attrib attribs[2];
    attribs[0].set(GL_FLOAT, 2, 8, false, (uint32_t)vtx, "ATTRIB_position");
    attribs[1].set(GL_FLOAT, 4, 16, false, (uint32_t)color, "ATTRIB_color");
    RsdVertexArray va(attribs, 2);
    va.setup(rsc);

    //LOGE("mSegmentCount %i", mSegmentCount);
    for (uint32_t ct=0; ct < mSegmentCount; ct++) {
        segment_t *s = &mSegments[ct];

        vtx[0] = s->x1;
        vtx[1] = s->y1;
        vtx[2] = s->xc;
        vtx[3] = s->yc;

        vtx[4] = s->x2;
        vtx[5] = s->y2;
        vtx[6] = s->xc;
        vtx[7] = s->yc;

        vtx[8] = s->x1;
        vtx[9] = s->y1;
        vtx[10] = s->x2;
        vtx[11] = s->y2;

        RSD_CALL_GL(glDrawArrays, GL_LINES, 0, 6);
    }

}

DrvPathDynamic::DrvPathDynamic() {
}

DrvPathDynamic::~DrvPathDynamic() {
}