#include <string>

#include <GL/glew.h>

#include <glshader.hpp>
#include <gltest.hpp>


GLTEST(2, 0, 640, 480, glshader)
{
    gltest_root("assets/tests");
    Shader::root("assets/shaders");

    // Create.
    GLTEST_EXPECT_EXCEPTION(false,
        Shader({"tests/create_noextension"}),
        "Failed to infer type of shader 'tests/create_noextension' of shader program 'tests/create_noextension'; "
        "no file extension."
    )
    GLTEST_EXPECT_EXCEPTION(false,
        Shader({"tests/create.unknownextension"}),
        "Failed to infer type of shader 'tests/create.unknownextension' of shader program 'tests/create.unknownextension'; "
        "unknown file extension 'unknownextension'."
    )
    GLTEST_EXPECT_EXCEPTION(true,
        Shader({"tests/create_nonexistent.vert"}),
        "Failed to source shader 'tests/create_nonexistent.vert' of shader program 'tests/create_nonexistent.vert'; "
        "could not open file 'assets/shaders/tests/create_nonexistent.vert':\n"
        "No such file or directory"
    )
    GLTEST_EXPECT_EXCEPTION(true,
        Shader({"tests/create_bad_compile.vert"}),
        "Failed to compile shader 'tests/create_bad_compile.vert' of shader program 'tests/create_bad_compile.vert':\n"
        "0:4(5): error: main() must return void\n"
    )
    GLTEST_EXPECT_EXCEPTION(true,
        Shader({"tests/create_bad_link.vert"}),
        "Failed to link shader program 'tests/create_bad_link.vert':\n"
        "error: vertex shader does not write to `gl_Position'. \n"
    )

    // Validate.
    GLTEST_EXPECT_EXCEPTION(true,
        Shader({"tests/validate_bad_samplers.vert"}).validate(),
        "Failed to validate shader program 'tests/validate_bad_samplers.vert':\n"
        "active samplers with a different type refer to the same texture image unit"
    )

    // Use.
    GLTEST_EXPECT_EXCEPTION(false,
        Shader({"tests/use.vert"}).validate(),
        "Failed to validate shader program 'tests/use.vert'; "
        "shader program not current."
    )

    // Version.
    GLTEST_EXPECT_EXCEPTION(false,
        Shader({"tests/version_none.vert"}),
        "Failed to source shader 'tests/version_none.vert' of shader program 'tests/version_none.vert'; "
        "found no #version."
    )
    GLTEST_EXPECT_EXCEPTION(false,
        Shader({"tests/version_malformed.vert"}),
        "Failed to source shader 'tests/version_malformed.vert' of shader program 'tests/version_malformed.vert'; "
        "malformed #version:\n"
        "assets/shaders/tests/version_malformed.vert:1: #version 1.10"
    )
    GLTEST_EXPECT_EXCEPTION(false,
        Shader({"tests/version_repeated.vert"}),
        "Failed to source shader 'tests/version_repeated.vert' of shader program 'tests/version_repeated.vert'; "
        "found repeated #version:\n"
        "assets/shaders/tests/version_repeated.vert:2: #version 110"
    )

    auto all = Shader({
        "tests/all.vert",
        "tests/all.frag",
    });

    all
        .use()
        .validate();

    constexpr auto size = 0.5F;
    glBegin(GL_TRIANGLE_STRIP);
    glVertex3f(-size, -size, 0.0F);
    glVertex3f(-size, +size, 0.0F);
    glVertex3f(+size, -size, 0.0F);
    glVertex3f(+size, +size, 0.0F);
    glEnd();

    GLTEST_EXPECT_FRAME("frame.data")
}