/*
 * Copyright © 2010-2011 Linaro Limited
 *
 * This file is part of the glmark2 OpenGL (ES) 2.0 benchmark.
 *
 * glmark2 is free software: you can redistribute it and/or modify it under the
 * terms of the GNU General Public License as published by the Free Software
 * Foundation, either version 3 of the License, or (at your option) any later
 * version.
 *
 * glmark2 is distributed in the hope that it will be useful, but WITHOUT ANY
 * WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
 * details.
 *
 * You should have received a copy of the GNU General Public License along with
 * glmark2.  If not, see <http://www.gnu.org/licenses/>.
 *
 * Authors:
 *  Alexandros Frantzis (glmark2)
 */
#include <cmath>

#include "scene.h"
#include "mat.h"
#include "stack.h"
#include "vec.h"
#include "log.h"
#include "shader-source.h"
#include "util.h"

static const std::string shader_file_base(GLMARK_DATA_PATH"/shaders/loop");

static const std::string vtx_file(shader_file_base + ".vert");
static const std::string frg_file(shader_file_base + ".frag");
static const std::string step_simple_file(shader_file_base + "-step-simple.all");
static const std::string step_loop_file(shader_file_base + "-step-loop.all");

SceneLoop::SceneLoop(Canvas &pCanvas) :
    SceneGrid(pCanvas, "loop")
{
    options_["fragment-steps"] = Scene::Option("fragment-steps", "1",
            "The number of computational steps in the fragment shader");
    options_["fragment-loop"] = Scene::Option("fragment-function", "true",
            "Whether to execute the steps in the vertex shader using a for loop");
    options_["vertex-steps"] = Scene::Option("vertex-steps", "1",
            "The number of computational steps in the vertex shader");
    options_["vertex-loop"] = Scene::Option("vertex-function", "true",
            "Whether to execute the steps in the vertex shader using a for loop");
    options_["vertex-uniform"] = Scene::Option("vertex-uniform", "true",
            "Whether to use a uniform in the vertex shader for the number of loop iterations to perform (i.e. vertex-steps)");
    options_["fragment-uniform"] = Scene::Option("fragment-uniform", "true",
            "Whether to use a uniform in the fragment shader for the number of loop iterations to perform (i.e. fragment-steps)");
}

SceneLoop::~SceneLoop()
{
}

static std::string
get_fragment_shader_source(int steps, bool loop, bool uniform)
{
    ShaderSource source(frg_file);
    ShaderSource source_main;

    if (loop) {
        source_main.append_file(step_loop_file);
        if (uniform) {
            source_main.replace("$NLOOPS$", "FragmentLoops");
        }
        else {
            source_main.replace("$NLOOPS$", Util::toString(steps));
        }
    }
    else {
        for (int i = 0; i < steps; i++)
            source_main.append_file(step_simple_file);
    }

    source.replace("$MAIN$", source_main.str());

    return source.str();
}

static std::string
get_vertex_shader_source(int steps, bool loop, bool uniform)
{
    ShaderSource source(vtx_file);
    ShaderSource source_main;

    if (loop) {
        source_main.append_file(step_loop_file);
        if (uniform) {
            source_main.replace("$NLOOPS$", "VertexLoops");
        }
        else {
            source_main.replace("$NLOOPS$", Util::toString(steps));
        }
    }
    else {
        for (int i = 0; i < steps; i++)
            source_main.append_file(step_simple_file);
    }

    source.replace("$MAIN$", source_main.str());

    return source.str();
}


void
SceneLoop::setup()
{
    SceneGrid::setup();

    /* Parse options */
    bool vtx_loop = options_["vertex-loop"].value == "true";
    bool frg_loop = options_["fragment-loop"].value == "true";
    bool vtx_uniform = options_["vertex-uniform"].value == "true";
    bool frg_uniform = options_["fragment-uniform"].value == "true";
    int vtx_steps = Util::fromString<int>(options_["vertex-steps"].value);
    int frg_steps = Util::fromString<int>(options_["fragment-steps"].value);

    /* Load shaders */
    std::string vtx_shader(get_vertex_shader_source(vtx_steps, vtx_loop,
                                                    vtx_uniform));
    std::string frg_shader(get_fragment_shader_source(frg_steps, frg_loop,
                                                      frg_uniform));

    if (!Scene::load_shaders_from_strings(program_, vtx_shader, frg_shader))
        return;

    program_.start();

    program_["VertexLoops"] = vtx_steps;
    program_["FragmentLoops"] = frg_steps;

    std::vector<GLint> attrib_locations;
    attrib_locations.push_back(program_["position"].location());
    mesh_.set_attrib_locations(attrib_locations);

    running_ = true;
    startTime_ = Util::get_timestamp_us() / 1000000.0;
    lastUpdateTime_ = startTime_;
}

Scene::ValidationResult
SceneLoop::validate()
{
    static const double radius_3d(std::sqrt(3.0 * 15.0 * 15.0));

    int frg_steps = Util::fromString<int>(options_["fragment-steps"].value);

    Canvas::Pixel ref;

    if (frg_steps == 5)
        ref = Canvas::Pixel(0x5e, 0x5e, 0x5e, 0xff);
    else
        return Scene::ValidationUnknown;

    Canvas::Pixel pixel = canvas_.read_pixel(293, 89);

    double dist = pixel.distance_rgb(ref);
    if (dist < radius_3d + 0.01) {
        return Scene::ValidationSuccess;
    }
    else {
        Log::debug("Validation failed! Expected: 0x%x Actual: 0x%x Distance: %f\n",
                    ref.to_le32(), pixel.to_le32(), dist);
        return Scene::ValidationFailure;
    }

    return Scene::ValidationUnknown;
}
