/*
 * Copyright 2023 Rive
 */

#include "rive/pls/gl/gl_state.hpp"

#include "shaders/constants.glsl"

namespace rive::pls
{
void GLState::invalidate()
{
    // Invalidate all cached state.
    memset(&m_validState, 0, sizeof(m_validState));

    // PLS only ever culls the CCW face when culling is enabled.
    glFrontFace(GL_CW);
    glDepthRangef(0, 1);
    glDepthFunc(GL_LESS);
    glClearDepthf(1);
    glClearStencil(0);

    // We always blend with premultiplied src-over when glBlendFunc is relevant.
    glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA);

    // ANGLE_shader_pixel_local_storage doesn't allow dither.
    glDisable(GL_DITHER);

#ifndef RIVE_ANDROID
    // D3D and Metal both have a provoking vertex convention of "first" for flat varyings, and it's
    // very costly for ANGLE to implement the OpenGL convention of "last" on these backends. To
    // workaround this, ANGLE provides the ANGLE_provoking_vertex extension. When this extension is
    // present, we can just set the provoking vertex to "first" and trust that it will be fast.
    if (m_capabilities.ANGLE_provoking_vertex)
    {
        glProvokingVertexANGLE(GL_FIRST_VERTEX_CONVENTION_ANGLE);
    }
#endif

    // Low-effort attempt to reset core state we don't use to default values.
    glDisable(GL_DEPTH_TEST);
    glDisable(GL_POLYGON_OFFSET_FILL);
#ifndef RIVE_WEBGL
    // https://www.khronos.org/registry/webgl/specs/latest/2.0/#5.18
    // WebGL 2.0 behaves as though PRIMITIVE_RESTART_FIXED_INDEX were always enabled.
    glDisable(GL_PRIMITIVE_RESTART_FIXED_INDEX);
#endif
    glDisable(GL_RASTERIZER_DISCARD);
    glDisable(GL_SAMPLE_ALPHA_TO_COVERAGE);
    glDisable(GL_SAMPLE_COVERAGE);
    glDisable(GL_SCISSOR_TEST);
    glDisable(GL_STENCIL_TEST);
    // glDisable(GL_COLOR_LOGIC_OP);
    // glDisable(GL_INDEX_LOGIC_OP);
    // glDisable(GL_ALPHA_TEST);
    glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
    glPixelStorei(GL_UNPACK_SKIP_ROWS, 0);
    glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0);
    glPixelStorei(GL_UNPACK_ALIGNMENT, 4);
    glPixelStorei(GL_PACK_ROW_LENGTH, 0);
    glPixelStorei(GL_PACK_SKIP_ROWS, 0);
    glPixelStorei(GL_PACK_SKIP_PIXELS, 0);
    glPixelStorei(GL_PACK_ALIGNMENT, 4);
}

constexpr static GLenum blend_mode_to_gl_equation(BlendMode blendMode)
{
    switch (blendMode)
    {
        case BlendMode::srcOver:
            return GL_FUNC_ADD;
        case BlendMode::screen:
            return GL_SCREEN_KHR;
        case BlendMode::overlay:
            return GL_OVERLAY_KHR;
        case BlendMode::darken:
            return GL_DARKEN_KHR;
        case BlendMode::lighten:
            return GL_LIGHTEN_KHR;
        case BlendMode::colorDodge:
            return GL_COLORDODGE_KHR;
        case BlendMode::colorBurn:
            return GL_COLORBURN_KHR;
        case BlendMode::hardLight:
            return GL_HARDLIGHT_KHR;
        case BlendMode::softLight:
            return GL_SOFTLIGHT_KHR;
        case BlendMode::difference:
            return GL_DIFFERENCE_KHR;
        case BlendMode::exclusion:
            return GL_EXCLUSION_KHR;
        case BlendMode::multiply:
            return GL_MULTIPLY_KHR;
        case BlendMode::hue:
            return GL_HSL_HUE_KHR;
        case BlendMode::saturation:
            return GL_HSL_SATURATION_KHR;
        case BlendMode::color:
            return GL_HSL_COLOR_KHR;
        case BlendMode::luminosity:
            return GL_HSL_LUMINOSITY_KHR;
    }
    RIVE_UNREACHABLE();
}

void GLState::setBlendEquation(BlendMode blendMode)
{
    GLenum blendEquation = blend_mode_to_gl_equation(blendMode);
    if (!m_validState.blendEquation || blendEquation != m_blendEquation)
    {
        if (!m_validState.blendEquation || m_blendEquation == GL_NONE)
        {
            glEnable(GL_BLEND);
        }
        glBlendEquation(blendEquation);
        m_blendEquation = blendEquation;
        m_validState.blendEquation = true;
    }
}

void GLState::disableBlending()
{
    if (!m_validState.blendEquation || m_blendEquation != GL_NONE)
    {
        glDisable(GL_BLEND);
        m_blendEquation = GL_NONE;
        m_validState.blendEquation = true;
    }
}

void GLState::setWriteMasks(bool colorWriteMask, bool depthWriteMask, GLuint stencilWriteMask)
{
    if (!m_validState.writeMasks)
    {
        glColorMask(colorWriteMask, colorWriteMask, colorWriteMask, colorWriteMask);
        glDepthMask(depthWriteMask);
        glStencilMask(stencilWriteMask);
        m_colorWriteMask = colorWriteMask;
        m_depthWriteMask = depthWriteMask;
        m_stencilWriteMask = stencilWriteMask;
        m_validState.writeMasks = true;
    }
    else
    {
        if (colorWriteMask != m_colorWriteMask)
        {
            glColorMask(colorWriteMask, colorWriteMask, colorWriteMask, colorWriteMask);
            m_colorWriteMask = colorWriteMask;
        }
        if (depthWriteMask != m_depthWriteMask)
        {
            glDepthMask(depthWriteMask);
            m_depthWriteMask = depthWriteMask;
        }
        if (stencilWriteMask != m_stencilWriteMask)
        {
            glStencilMask(stencilWriteMask);
            m_stencilWriteMask = stencilWriteMask;
        }
    }
}

void GLState::setCullFace(GLenum cullFace)
{
    if (!m_validState.cullFace || cullFace != m_cullFace)
    {
        if (cullFace == GL_NONE)
        {
            glDisable(GL_CULL_FACE);
        }
        else
        {
            if (!m_validState.cullFace || m_cullFace == GL_NONE)
            {
                glEnable(GL_CULL_FACE);
            }
            glCullFace(cullFace);
        }
        m_cullFace = cullFace;
        m_validState.cullFace = true;
    }
}

void GLState::bindProgram(GLuint programID)
{
    if (!m_validState.boundProgramID || programID != m_boundProgramID)
    {
        glUseProgram(programID);
        m_boundProgramID = programID;
        m_validState.boundProgramID = true;
    }
}

void GLState::bindVAO(GLuint vao)
{
    if (!m_validState.boundVAO || vao != m_boundVAO)
    {
        glBindVertexArray(vao);
        m_boundVAO = vao;
        m_validState.boundVAO = true;
    }
}

void GLState::bindBuffer(GLenum target, GLuint bufferID)
{
    switch (target)
    {
        default:
            // Don't track GL_ELEMENT_ARRAY_BUFFER, since it is tied to the VAO state.
            glBindBuffer(target, bufferID);
            return;
        case GL_ARRAY_BUFFER:
            if (!m_validState.boundArrayBufferID || bufferID != m_boundArrayBufferID)
            {
                glBindBuffer(GL_ARRAY_BUFFER, bufferID);
                m_boundArrayBufferID = bufferID;
                m_validState.boundArrayBufferID = true;
            }
            break;
        case GL_UNIFORM_BUFFER:
            if (!m_validState.boundUniformBufferID || bufferID != m_boundUniformBufferID)
            {
                glBindBuffer(GL_UNIFORM_BUFFER, bufferID);
                m_boundUniformBufferID = bufferID;
                m_validState.boundUniformBufferID = true;
            }
            break;
        case GL_PIXEL_UNPACK_BUFFER:
            if (!m_validState.boundPixelUnpackBufferID || bufferID != m_boundPixelUnpackBufferID)
            {
                glBindBuffer(GL_PIXEL_UNPACK_BUFFER, bufferID);
                m_boundPixelUnpackBufferID = bufferID;
                m_validState.boundPixelUnpackBufferID = true;
            }
            break;
    }
}

void GLState::deleteProgram(GLuint programID)
{
    glDeleteProgram(programID);
    if (m_validState.boundProgramID && m_boundProgramID == programID)
        m_boundProgramID = 0;
}

void GLState::deleteVAO(GLuint vao)
{
    glDeleteVertexArrays(1, &vao);
    if (m_validState.boundVAO && m_boundVAO == vao)
        m_boundVAO = 0;
}

void GLState::deleteBuffer(GLuint bufferID)
{
    glDeleteBuffers(1, &bufferID);
    if (m_validState.boundArrayBufferID && m_boundArrayBufferID == bufferID)
        m_boundArrayBufferID = 0;
    if (m_validState.boundUniformBufferID && m_boundUniformBufferID == bufferID)
        m_boundUniformBufferID = 0;
    if (m_validState.boundPixelUnpackBufferID && m_boundPixelUnpackBufferID == bufferID)
        m_boundPixelUnpackBufferID = 0;
}
} // namespace rive::pls
