/*
 * Copyright (C) 2010 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.
 */

#define LOG_TAG "OpenGLRenderer"

#include <cmath>

#include <utils/Log.h>

#include "Caches.h"
#include "Patch.h"
#include "Properties.h"
#include "UvMapper.h"

namespace android {
namespace uirenderer {

///////////////////////////////////////////////////////////////////////////////
// Constructors/destructor
///////////////////////////////////////////////////////////////////////////////

Patch::Patch(): vertices(NULL), verticesCount(0), indexCount(0), hasEmptyQuads(false) {
}

Patch::~Patch() {
    delete[] vertices;
}

///////////////////////////////////////////////////////////////////////////////
// Vertices management
///////////////////////////////////////////////////////////////////////////////

uint32_t Patch::getSize() const {
    return verticesCount * sizeof(TextureVertex);
}

TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
        float width, float height, const Res_png_9patch* patch) {
    UvMapper mapper;
    return createMesh(bitmapWidth, bitmapHeight, width, height, mapper, patch);
}

TextureVertex* Patch::createMesh(const float bitmapWidth, const float bitmapHeight,
        float width, float height, const UvMapper& mapper, const Res_png_9patch* patch) {
    if (vertices) return vertices;

    int8_t emptyQuads = 0;
    mColors = patch->getColors();

    const int8_t numColors = patch->numColors;
    if (uint8_t(numColors) < sizeof(uint32_t) * 4) {
        for (int8_t i = 0; i < numColors; i++) {
            if (mColors[i] == 0x0) {
                emptyQuads++;
            }
        }
    }

    hasEmptyQuads = emptyQuads > 0;

    uint32_t xCount = patch->numXDivs;
    uint32_t yCount = patch->numYDivs;

    uint32_t maxVertices = ((xCount + 1) * (yCount + 1) - emptyQuads) * 4;
    if (maxVertices == 0) return NULL;

    TextureVertex* tempVertices = new TextureVertex[maxVertices];
    TextureVertex* vertex = tempVertices;

    const int32_t* xDivs = patch->getXDivs();
    const int32_t* yDivs = patch->getYDivs();

    const uint32_t xStretchCount = (xCount + 1) >> 1;
    const uint32_t yStretchCount = (yCount + 1) >> 1;

    float stretchX = 0.0f;
    float stretchY = 0.0f;

    float rescaleX = 1.0f;
    float rescaleY = 1.0f;

    if (xStretchCount > 0) {
        uint32_t stretchSize = 0;
        for (uint32_t i = 1; i < xCount; i += 2) {
            stretchSize += xDivs[i] - xDivs[i - 1];
        }
        const float xStretchTex = stretchSize;
        const float fixed = bitmapWidth - stretchSize;
        const float xStretch = fmaxf(width - fixed, 0.0f);
        stretchX = xStretch / xStretchTex;
        rescaleX = fixed == 0.0f ? 0.0f : fminf(fmaxf(width, 0.0f) / fixed, 1.0f);
    }

    if (yStretchCount > 0) {
        uint32_t stretchSize = 0;
        for (uint32_t i = 1; i < yCount; i += 2) {
            stretchSize += yDivs[i] - yDivs[i - 1];
        }
        const float yStretchTex = stretchSize;
        const float fixed = bitmapHeight - stretchSize;
        const float yStretch = fmaxf(height - fixed, 0.0f);
        stretchY = yStretch / yStretchTex;
        rescaleY = fixed == 0.0f ? 0.0f : fminf(fmaxf(height, 0.0f) / fixed, 1.0f);
    }

    uint32_t quadCount = 0;

    float previousStepY = 0.0f;

    float y1 = 0.0f;
    float y2 = 0.0f;
    float v1 = 0.0f;

    mUvMapper = mapper;

    for (uint32_t i = 0; i < yCount; i++) {
        float stepY = yDivs[i];
        const float segment = stepY - previousStepY;

        if (i & 1) {
            y2 = y1 + floorf(segment * stretchY + 0.5f);
        } else {
            y2 = y1 + segment * rescaleY;
        }

        float vOffset = y1 == y2 ? 0.0f : 0.5 - (0.5 * segment / (y2 - y1));
        float v2 = fmax(0.0f, stepY - vOffset) / bitmapHeight;
        v1 += vOffset / bitmapHeight;

        if (stepY > 0.0f) {
            generateRow(xDivs, xCount, vertex, y1, y2, v1, v2, stretchX, rescaleX,
                    width, bitmapWidth, quadCount);
        }

        y1 = y2;
        v1 = stepY / bitmapHeight;

        previousStepY = stepY;
    }

    if (previousStepY != bitmapHeight) {
        y2 = height;
        generateRow(xDivs, xCount, vertex, y1, y2, v1, 1.0f, stretchX, rescaleX,
                width, bitmapWidth, quadCount);
    }

    if (verticesCount == maxVertices) {
        vertices = tempVertices;
    } else {
        vertices = new TextureVertex[verticesCount];
        memcpy(vertices, tempVertices, verticesCount * sizeof(TextureVertex));
        delete[] tempVertices;
    }

    return vertices;
}

void Patch::generateRow(const int32_t* xDivs, uint32_t xCount, TextureVertex*& vertex,
        float y1, float y2, float v1, float v2, float stretchX, float rescaleX,
        float width, float bitmapWidth, uint32_t& quadCount) {
    float previousStepX = 0.0f;

    float x1 = 0.0f;
    float x2 = 0.0f;
    float u1 = 0.0f;

    // Generate the row quad by quad
    for (uint32_t i = 0; i < xCount; i++) {
        float stepX = xDivs[i];
        const float segment = stepX - previousStepX;

        if (i & 1) {
            x2 = x1 + floorf(segment * stretchX + 0.5f);
        } else {
            x2 = x1 + segment * rescaleX;
        }

        float uOffset = x1 == x2 ? 0.0f : 0.5 - (0.5 * segment / (x2 - x1));
        float u2 = fmax(0.0f, stepX - uOffset) / bitmapWidth;
        u1 += uOffset / bitmapWidth;

        if (stepX > 0.0f) {
            generateQuad(vertex, x1, y1, x2, y2, u1, v1, u2, v2, quadCount);
        }

        x1 = x2;
        u1 = stepX / bitmapWidth;

        previousStepX = stepX;
    }

    if (previousStepX != bitmapWidth) {
        x2 = width;
        generateQuad(vertex, x1, y1, x2, y2, u1, v1, 1.0f, v2, quadCount);
    }
}

void Patch::generateQuad(TextureVertex*& vertex, float x1, float y1, float x2, float y2,
            float u1, float v1, float u2, float v2, uint32_t& quadCount) {
    const uint32_t oldQuadCount = quadCount;
    quadCount++;

    if (x1 < 0.0f) x1 = 0.0f;
    if (x2 < 0.0f) x2 = 0.0f;
    if (y1 < 0.0f) y1 = 0.0f;
    if (y2 < 0.0f) y2 = 0.0f;

    // Skip degenerate and transparent (empty) quads
    if ((mColors[oldQuadCount] == 0) || x1 >= x2 || y1 >= y2) {
#if DEBUG_PATCHES_EMPTY_VERTICES
        PATCH_LOGD("    quad %d (empty)", oldQuadCount);
        PATCH_LOGD("        left,  top    = %.2f, %.2f\t\tu1, v1 = %.8f, %.8f", x1, y1, u1, v1);
        PATCH_LOGD("        right, bottom = %.2f, %.2f\t\tu2, v2 = %.8f, %.8f", x2, y2, u2, v2);
#endif
        return;
    }

    // Record all non empty quads
    if (hasEmptyQuads) {
        Rect bounds(x1, y1, x2, y2);
        quads.add(bounds);
    }

    mUvMapper.map(u1, v1, u2, v2);

    TextureVertex::set(vertex++, x1, y1, u1, v1);
    TextureVertex::set(vertex++, x2, y1, u2, v1);
    TextureVertex::set(vertex++, x1, y2, u1, v2);
    TextureVertex::set(vertex++, x2, y2, u2, v2);

    verticesCount += 4;
    indexCount += 6;

#if DEBUG_PATCHES_VERTICES
    PATCH_LOGD("    quad %d", oldQuadCount);
    PATCH_LOGD("        left,  top    = %.2f, %.2f\t\tu1, v1 = %.8f, %.8f", x1, y1, u1, v1);
    PATCH_LOGD("        right, bottom = %.2f, %.2f\t\tu2, v2 = %.8f, %.8f", x2, y2, u2, v2);
#endif
}

}; // namespace uirenderer
}; // namespace android
