/*
 * 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_ = Scene::get_timestamp_us() / 1000000.0;
    lastUpdateTime_ = startTime_;
}

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

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

    Canvas::Pixel ref;

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

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

    double dist = pixel_value_distance(pixel, 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;
}
