//
// Copyright 2025 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

#include "tests/test_utils/CompilerTest.h"

GLuint CompiledShader::compile(GLenum type, const char *source)
{
    mShader = glCreateShader(type);

    const char *sourceArray[1] = {source};
    glShaderSource(mShader, 1, sourceArray, nullptr);
    glCompileShader(mShader);

    GLint compileResult;
    glGetShaderiv(mShader, GL_COMPILE_STATUS, &compileResult);

    GLint infoLogLength;
    glGetShaderiv(mShader, GL_INFO_LOG_LENGTH, &infoLogLength);
    mInfoLog.clear();

    if (infoLogLength > 0)
    {
        std::vector<GLchar> infoLog(infoLogLength);
        glGetShaderInfoLog(mShader, infoLogLength, nullptr, infoLog.data());

        // Note: the info log is nul-terminated.
        mInfoLog = infoLog.data();
    }

    if (compileResult == 0)
    {
        std::cerr << "shader compilation failed: "
                  << (mInfoLog.empty() ? "<Empty message log>" : mInfoLog.data()) << "\n";

        destroy();
    }
    else if (IsGLExtensionEnabled("GL_ANGLE_translated_shader_source"))
    {
        GLint translatedSourceLength;
        glGetShaderiv(mShader, GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE, &translatedSourceLength);

        if (translatedSourceLength > 0)
        {
            std::vector<GLchar> translatedSource(translatedSourceLength);
            glGetTranslatedShaderSourceANGLE(mShader, translatedSourceLength, nullptr,
                                             translatedSource.data());

            // Note: the translatedSource is nul-terminated.
            mTranslatedSource = translatedSource.data();
        }
    }

    return mShader;
}

CompiledShader::~CompiledShader()
{
    if (mShader != 0)
    {
        destroy();
    }
}

void CompiledShader::destroy()
{
    glDeleteShader(mShader);
    ASSERT_GL_NO_ERROR();
    mShader = 0;

    mTranslatedSource.clear();
}

bool CompiledShader::hasInfoLog(const char *expect) const
{
    return mInfoLog.find(expect) != std::string::npos;
}

bool CompiledShader::verifyInTranslatedSource(const char *expect) const
{
    return mTranslatedSource.empty() || mTranslatedSource.find(expect) != std::string::npos;
}

bool CompiledShader::verifyNotInTranslatedSource(const char *expect) const
{
    return mTranslatedSource.empty() || mTranslatedSource.find(expect) == std::string::npos;
}

bool CompiledShader::verifyCountInTranslatedSource(const char *expect, size_t expectCount) const
{
    if (mTranslatedSource.empty())
    {
        return true;
    }

    size_t count               = 0;
    std::string::size_type pos = 0;
    while (true)
    {
        pos = mTranslatedSource.find(expect, pos);
        if (pos == std::string::npos)
        {
            break;
        }
        ++count;
        ++pos;
    }
    return count == expectCount;
}

void CompilerTest::testSetUp() {}

void CompilerTest::testTearDown()
{
    reset();
}

void CompilerTest::reset()
{
    mVertexShader.destroy();
    mTessellationControlShader.destroy();
    mTessellationEvaluationShader.destroy();
    mGeometryShader.destroy();
    mFragmentShader.destroy();
    mComputeShader.destroy();

    glDeleteProgram(mProgram);
    mProgram = 0;
}

const CompiledShader &CompilerTest::compile(GLenum type, const char *source)
{
    CompiledShader &shader = getCompiledShader(type);
    shader.compile(type, source);
    return shader;
}

CompiledShader &CompilerTest::getCompiledShader(GLenum type)
{
    switch (type)
    {
        case GL_VERTEX_SHADER:
            return mVertexShader;
        case GL_TESS_CONTROL_SHADER:
            return mTessellationControlShader;
        case GL_TESS_EVALUATION_SHADER:
            return mTessellationEvaluationShader;
        case GL_GEOMETRY_SHADER:
            return mGeometryShader;
        case GL_FRAGMENT_SHADER:
            return mFragmentShader;
        case GL_COMPUTE_SHADER:
            return mComputeShader;
        default:
            // Unsupported type
            ASSERT(false);
            return mVertexShader;
    }
}

GLuint CompilerTest::link()
{
    mProgram = glCreateProgram();

    if (mComputeShader.success())
    {
        glAttachShader(mProgram, mComputeShader.getShader());
    }
    else
    {
        if (mVertexShader.success())
        {
            glAttachShader(mProgram, mVertexShader.getShader());
        }
        if (mTessellationControlShader.success())
        {
            glAttachShader(mProgram, mTessellationControlShader.getShader());
        }
        if (mTessellationEvaluationShader.success())
        {
            glAttachShader(mProgram, mTessellationEvaluationShader.getShader());
        }
        if (mGeometryShader.success())
        {
            glAttachShader(mProgram, mGeometryShader.getShader());
        }
        if (mFragmentShader.success())
        {
            glAttachShader(mProgram, mFragmentShader.getShader());
        }
    }

    glLinkProgram(mProgram);
    EXPECT_GL_NO_ERROR();

    GLint linkStatus;
    glGetProgramiv(mProgram, GL_LINK_STATUS, &linkStatus);
    EXPECT_NE(linkStatus, 0);

    return mProgram;
}
