/*
 * 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)
 *  Jesse Barker
 */
#include "scene.h"
#include "log.h"
#include "mat.h"
#include "stack.h"
#include "shader-source.h"
#include "util.h"
#include "gl-headers.h"
#include <cmath>

/***********************
 * Wave implementation *
 ***********************/

/**
 * A callback used to set up the grid by the Wave class.
 * It is called for each "quad" of the grid.
 */
static void
wave_grid_conf(Mesh &mesh, int x, int y, int n_x, int n_y,
               LibMatrix::vec3 &ul,
               LibMatrix::vec3 &ll,
               LibMatrix::vec3 &ur,
               LibMatrix::vec3 &lr)
{
    // These parameters are unused in this instance of a virtual callback
    // function.
    static_cast<void>(x);
    static_cast<void>(y);
    static_cast<void>(n_x);
    static_cast<void>(n_y);

    /*
     * Order matters here, so that Wave::vertex_length_index() can work.
     * Vertices of the triangles at index i that belong to length index i
     * are even, those that belong to i + 1 are odd.
     */
    const LibMatrix::vec3* t[] = {
        &ll, &ur, &ul, &ur, &ll, &lr
    };

    for (int i = 0; i < 6; i++) {
        mesh.next_vertex();
        /*
         * Set the vertex position and the three vertex positions
         * of the triangle this vertex belongs to.
         */
        mesh.set_attrib(0, *t[i]);
        mesh.set_attrib(1, *t[3 * (i / 3)]);
        mesh.set_attrib(2, *t[3 * (i / 3) + 1]);
        mesh.set_attrib(3, *t[3 * (i / 3) + 2]);
    }
}

/**
 * Renders a grid mesh modulated by a sine wave
 */
class WaveMesh
{
public:
    /**
     * Creates a wave mesh.
     *
     * @param length the total length of the grid (in model coordinates)
     * @param width the total width of the grid (in model coordinates)
     * @param nlength the number of length-wise grid subdivisions
     * @param nwidth the number of width-wise grid subdivisions
     * @param wavelength the wave length as a proportion of the length
     * @param duty_cycle the duty cycle ()
     */
    WaveMesh(double length, double width, size_t nlength, size_t nwidth,
             double wavelength, double duty_cycle) :
        length_(length), width_(width), nlength_(nlength), nwidth_(nwidth),
        wave_k_(2 * M_PI / (wavelength * length)),
        wave_period_(2.0 * M_PI / wave_k_),
        wave_full_period_(wave_period_ / duty_cycle),
        wave_velocity_(0.1 * length), displacement_(nlength + 1)
    {
        create_program();
        create_mesh();
    }


    ~WaveMesh() { reset(); }

    /**
     * Updates the state of a wave mesh.
     *
     * @param elapsed the time elapsed since the beginning of the rendering
     */
    void update(double elapsed)
    {
        std::vector<std::vector<float> >& vertices(mesh_.vertices());

        /* Figure out which length index ranges need update */
        std::vector<std::pair<size_t, size_t> > ranges;

        for (size_t n = 0; n <= nlength_; n++) {
            double d(displacement(n, elapsed));

            if (d != displacement_[n]) {
                if (ranges.size() > 0 && ranges.back().second == n - 1) {
                    ranges.back().second = n;
                }
                else {
                    ranges.push_back(
                            std::pair<size_t, size_t>(n > 0 ? n - 1 : 0, n)
                            );
                }
            }

            displacement_[n] = d;
        }

        /* Update the vertex data of the changed ranges */
        for (std::vector<std::pair<size_t, size_t> >::iterator iter = ranges.begin();
             iter != ranges.end();
             iter++)
        {
            /* First vertex of length index range */
            size_t vstart(iter->first * nwidth_ * 6 + (iter->first % 2));
            /*
             * First vertex not included in the range. We should also update all
             * vertices of triangles touching index i.
             */
            size_t vend((iter->second + (iter->second < nlength_)) * nwidth_ * 6);

            for (size_t v = vstart; v < vend; v++) {
                size_t vt = 3 * (v / 3);
                vertices[v][0 * 3 + 2] = displacement_[vertex_length_index(v)];
                vertices[v][1 * 3 + 2] = displacement_[vertex_length_index(vt)];
                vertices[v][2 * 3 + 2] = displacement_[vertex_length_index(vt + 1)];
                vertices[v][3 * 3 + 2] = displacement_[vertex_length_index(vt + 2)];
            }

            /* Update pair with actual vertex range */
            iter->first = vstart;
            iter->second = vend - 1;
        }

        mesh_.update_vbo(ranges);
    }

    Mesh& mesh() { return mesh_; }
    Program& program() { return program_; }

    void reset()
    {
        program_.stop();
        program_.release();
        mesh_.reset();
    }

private:
    Mesh mesh_;
    Program program_;
    double length_;
    double width_;
    size_t nlength_;
    size_t nwidth_;
    /* Wave parameters */
    double wave_k_;
    double wave_period_;
    double wave_full_period_;
    double wave_fill_;
    double wave_velocity_;

    std::vector<double> displacement_;

    /**
     * Calculates the length index of a vertex.
     */
    size_t vertex_length_index(size_t v)
    {
        return v / (6 * nwidth_) + (v % 2);
    }

    /**
     * The sine wave function with duty-cycle.
     *
     * @param x the space coordinate
     *
     * @return the operation error code
     */
    double wave_func(double x)
    {
        double r(fmod(x, wave_full_period_));
        if (r < 0)
            r += wave_full_period_;

        /*
         * Return either the sine value or 0.0, depending on the
         * wave duty cycle.
         */
        if (r > wave_period_)
        {
            return 0;
        }
        else
        {
            return 0.2 * std::sin(wave_k_ * r);
        }
    }

    /**
     * Calculates the displacement of the wave.
     *
     * @param n the length index
     * @param elapsed the time elapsed since the beginning of the rendering
     *
     * @return the displacement at point n at time elapsed
     */
    double displacement(size_t n, double elapsed)
    {
        double x(n * length_ / nlength_);

        return wave_func(x - wave_velocity_ * elapsed);
    }

    /**
     * Creates the GL shader program.
     */
    void create_program()
    {
        /* Set up shaders */
        static const std::string vtx_shader_filename(
                GLMARK_DATA_PATH"/shaders/buffer-wireframe.vert");
        static const std::string frg_shader_filename(
                GLMARK_DATA_PATH"/shaders/buffer-wireframe.frag");

        ShaderSource vtx_source(vtx_shader_filename);
        ShaderSource frg_source(frg_shader_filename);

        if (!Scene::load_shaders_from_strings(program_, vtx_source.str(),
                                              frg_source.str()))
        {
            return;
        }
    }

    /**
     * Creates the grid mesh.
     */
    void create_mesh()
    {
        /*
         * We need to pass the positions of all vertex of the triangle
         * in order to draw the wireframe.
         */
        std::vector<int> vertex_format;
        vertex_format.push_back(3);     // Position of vertex
        vertex_format.push_back(3);     // Position of triangle vertex 0
        vertex_format.push_back(3);     // Position of triangle vertex 1
        vertex_format.push_back(3);     // Position of triangle vertex 2
        mesh_.set_vertex_format(vertex_format);

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

        mesh_.make_grid(nlength_, nwidth_, length_, width_,
                        0.0, wave_grid_conf);
    }

};

/******************************
 * SceneBuffer implementation *
 ******************************/

struct SceneBufferPrivate {
    WaveMesh *wave;
    SceneBufferPrivate() : wave(0) {}
    ~SceneBufferPrivate() { delete wave; }
};

SceneBuffer::SceneBuffer(Canvas &pCanvas) :
    Scene(pCanvas, "buffer")
{
    priv_ = new SceneBufferPrivate();
    options_["interleave"] = Scene::Option("interleave", "false",
                                           "Whether to interleave vertex attribute data",
                                           "false,true");
    options_["update-method"] = Scene::Option("update-method", "map",
                                              "Which method to use to update vertex data",
                                              "map,subdata");
    options_["update-fraction"] = Scene::Option("update-fraction", "1.0",
                                                "The fraction of the mesh length that is updated at every iteration (0.0-1.0)");
    options_["update-dispersion"] = Scene::Option("update-dispersion", "0.0",
                                                  "How dispersed the updates are [0.0 - 1.0]");
    options_["columns"] = Scene::Option("columns", "100",
                                       "The number of mesh subdivisions length-wise");
    options_["rows"] = Scene::Option("rows", "20",
                                      "The number of mesh subdisivisions width-wise");
    options_["buffer-usage"] = Scene::Option("buffer-usage", "static",
                                             "How the buffer will be used",
                                             "static,stream,dynamic");
}

SceneBuffer::~SceneBuffer()
{
    delete priv_;
}

bool
SceneBuffer::load()
{
    running_ = false;

    return true;
}

void
SceneBuffer::unload()
{
}

void
SceneBuffer::setup()
{
    using LibMatrix::vec3;

    Scene::setup();

    bool should_run = true;
    bool interleave = (options_["interleave"].value == "true");
    Mesh::VBOUpdateMethod update_method;
    Mesh::VBOUsage usage;
    double update_fraction;
    double update_dispersion;
    size_t nlength;
    size_t nwidth;

    if (options_["update-method"].value == "map")
        update_method = Mesh::VBOUpdateMethodMap;
    else if (options_["update-method"].value == "subdata")
        update_method = Mesh::VBOUpdateMethodSubData;
    else
        update_method = Mesh::VBOUpdateMethodMap;

    if (options_["buffer-usage"].value == "static")
        usage = Mesh::VBOUsageStatic;
    else if (options_["buffer-usage"].value == "stream")
        usage = Mesh::VBOUsageStream;
    else
        usage = Mesh::VBOUsageDynamic;

    update_fraction = Util::fromString<double>(options_["update-fraction"].value);
    update_dispersion = Util::fromString<double>(options_["update-dispersion"].value);
    nlength = Util::fromString<size_t>(options_["columns"].value);
    nwidth = Util::fromString<size_t>(options_["rows"].value);

    if (update_method == Mesh::VBOUpdateMethodMap &&
        (GLExtensions::MapBuffer == 0 || GLExtensions::UnmapBuffer == 0))
    {
        Log::error("Requested MapBuffer VBO update method but GL_OES_mapbuffer"
                   " is not supported!\n");
        should_run = false;
    }

    priv_->wave = new WaveMesh(5.0, 2.0, nlength, nwidth,
                               update_fraction * (1.0 - update_dispersion + 0.0001),
                               update_fraction);

    priv_->wave->mesh().interleave(interleave);
    priv_->wave->mesh().vbo_update_method(update_method);
    priv_->wave->mesh().vbo_usage(usage);
    priv_->wave->mesh().build_vbo();

    priv_->wave->program().start();
    priv_->wave->program()["Viewport"] = LibMatrix::vec2(canvas_.width(), canvas_.height());

    glDisable(GL_CULL_FACE);

    currentFrame_ = 0;
    running_ = should_run;
    startTime_ = Util::get_timestamp_us() / 1000000.0;
    lastUpdateTime_ = startTime_;
}

void
SceneBuffer::teardown()
{
    delete priv_->wave;
    priv_->wave = 0;

    glEnable(GL_CULL_FACE);

    Scene::teardown();
}

void
SceneBuffer::update()
{
    Scene::update();

    double elapsed_time = lastUpdateTime_ - startTime_;

    priv_->wave->update(elapsed_time);
}

void
SceneBuffer::draw()
{
    LibMatrix::Stack4 model_view;

    // Load the ModelViewProjectionMatrix uniform in the shader
    LibMatrix::mat4 model_view_proj(canvas_.projection());
    model_view.translate(0.0, 0.0, -4.0);
    model_view.rotate(45.0, -1.0, 0.0, 0.0);
    model_view_proj *= model_view.getCurrent();

    priv_->wave->program()["ModelViewProjectionMatrix"] = model_view_proj;

    priv_->wave->mesh().render_vbo();
}

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

    Canvas::Pixel ref(0x34, 0x99, 0xd7, 0xff);
    Canvas::Pixel pixel = canvas_.read_pixel(402, 189);

    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;
}
