/*
 * Copyright © 2012 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
 */
#include "scene.h"
#include "mat.h"
#include "stack.h"
#include "vec.h"
#include "log.h"
#include "mesh.h"
#include "util.h"
#include "texture.h"
#include "shader-source.h"
#include "renderer.h"

using LibMatrix::vec2;
using LibMatrix::vec3;
using LibMatrix::vec4;
using LibMatrix::mat4;

class SceneTerrainPrivate
{
public:
    SceneTerrainPrivate(Canvas &canvas, const LibMatrix::vec2 &repeat_overlay,
                        bool use_bloom, bool use_tilt_shift) :
        canvas(canvas), repeat_overlay(repeat_overlay),
        use_bloom(use_bloom), use_tilt_shift(use_tilt_shift),
        terrain_renderer(0), bloom_v_renderer(0), bloom_h_renderer(0),
        overlay_renderer(0), tilt_v_renderer(0), tilt_h_renderer(0),
        copy_renderer(0), height_map_renderer(0), normal_map_renderer(0),
        specular_map_renderer(0),
        height_normal_chain(0), bloom_chain(0), tilt_chain(0), terrain_chain(0)
    {
        init_renderers();
    }

    ~SceneTerrainPrivate()
    {
        release_renderers();
    }

    void init_renderers()
    {
        /* Create and set up renderers */
        const vec2 map_res(256.0f, 256.0f);
        const vec2 screen_res(canvas.width(), canvas.height());
        const vec2 bloom_res(256.0f, 256.0f);
        const vec2 grass_res(512.0f, 512.0f);

        height_map_renderer = new SimplexNoiseRenderer(map_res);
        height_map_renderer->setup(height_map_renderer->size(), false, false);

        normal_map_renderer = new NormalFromHeightRenderer(map_res);
        normal_map_renderer->setup(normal_map_renderer->size(), false, false);

        specular_map_renderer = new LuminanceRenderer(grass_res);
        specular_map_renderer->setup_texture(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,
                                             GL_REPEAT, GL_REPEAT);
        specular_map_renderer->setup(specular_map_renderer->size(), false, false);

        terrain_renderer = new TerrainRenderer(screen_res, repeat_overlay);
        terrain_renderer->setup(terrain_renderer->size(),
                                !use_bloom && !use_tilt_shift,
                                true);
        terrain_renderer->setup_texture(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,
                                        GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);

        /* Bloom */
        if (use_bloom) {
            bloom_h_renderer = new BlurRenderer(bloom_res, 2, 4.0,
                                                BlurRenderer::BlurDirectionHorizontal,
                                                vec2(1.0, 1.0) / screen_res,
                                                0.0);
            bloom_h_renderer->setup_texture(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,
                                            GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
            bloom_h_renderer->setup(bloom_h_renderer->size(), false, false);

            bloom_v_renderer = new BlurRenderer(bloom_res, 2, 4.0,
                                                BlurRenderer::BlurDirectionVertical,
                                                vec2(1.0, 1.0) / bloom_res,
                                                0.0);
            bloom_v_renderer->setup_texture(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,
                                            GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
            bloom_v_renderer->setup(bloom_v_renderer->size(), false, false);
            overlay_renderer = new OverlayRenderer(*terrain_renderer, 0.6);
        }

        /* Tilt-shift */
        if (use_tilt_shift) {
            tilt_h_renderer = new BlurRenderer(screen_res, 4, 2.7,
                                               BlurRenderer::BlurDirectionHorizontal,
                                               vec2(1.0, 1.0) / screen_res,
                                               0.5);
            tilt_h_renderer->setup_texture(GL_LINEAR_MIPMAP_LINEAR, GL_LINEAR,
                                           GL_CLAMP_TO_EDGE, GL_CLAMP_TO_EDGE);
            tilt_h_renderer->setup(tilt_h_renderer->size(), false, false);

            tilt_v_renderer = new BlurRenderer(screen_res, 4, 2.7,
                                               BlurRenderer::BlurDirectionVertical,
                                               vec2(1.0, 1.0) / screen_res,
                                               0.5);
        }

        /* Copy renderer */
        if (use_bloom && !use_tilt_shift)
            copy_renderer = new CopyRenderer(screen_res);

        /* Height normal chain */
        height_normal_chain = new RendererChain();
        height_normal_chain->append(*height_map_renderer);
        height_normal_chain->append(*normal_map_renderer);

        /* Bloom effect chain */
        if (use_bloom) {
            bloom_chain = new RendererChain();
            bloom_chain->append(*bloom_h_renderer);
            bloom_chain->append(*bloom_v_renderer);
            bloom_chain->append(*overlay_renderer);
        }

        /* Tilt-shift effect chain */
        if (use_tilt_shift) {
            tilt_chain = new RendererChain();
            tilt_chain->append(*tilt_h_renderer);
            tilt_chain->append(*tilt_v_renderer);
        }

        /* Terrain chain */
        terrain_chain = new RendererChain();
        terrain_chain->append(*terrain_renderer);
        if (use_bloom)
            terrain_chain->append(*bloom_chain);
        if (use_tilt_shift)
            terrain_chain->append(*tilt_chain);

        /*
         * If are just using bloom, the terrain is rendered to a texture and
         * bloom applied on that texture. We need to "copy" that texture's
         * contents to the screen to make the scene visible.
         */
        if (use_bloom && !use_tilt_shift)
            terrain_chain->append(*copy_renderer);

        /*
         * Set up renderer textures.
         */
        terrain_renderer->height_map_texture(height_map_renderer->texture());
        terrain_renderer->normal_map_texture(normal_map_renderer->texture());
        terrain_renderer->specular_map_texture(specular_map_renderer->texture());

        specular_map_renderer->input_texture(terrain_renderer->diffuse1_texture());
    }

    void release_renderers()
    {
        delete terrain_chain;
        delete bloom_chain;
        delete tilt_chain;
        delete height_normal_chain;

        delete height_map_renderer;
        delete normal_map_renderer;
        delete specular_map_renderer;
        delete terrain_renderer;
        delete bloom_v_renderer;
        delete bloom_h_renderer;
        delete overlay_renderer;
        delete tilt_v_renderer;
        delete tilt_h_renderer;
        delete copy_renderer;
    }

    Canvas &canvas;
    LibMatrix::vec2 repeat_overlay;
    bool use_bloom;
    bool use_tilt_shift;

    /* Renderers */
    TerrainRenderer *terrain_renderer;
    BlurRenderer *bloom_v_renderer;
    BlurRenderer *bloom_h_renderer;
    OverlayRenderer *overlay_renderer;
    BlurRenderer *tilt_v_renderer;
    BlurRenderer *tilt_h_renderer;
    CopyRenderer *copy_renderer;

    SimplexNoiseRenderer *height_map_renderer;
    NormalFromHeightRenderer *normal_map_renderer;
    LuminanceRenderer *specular_map_renderer;

    /* Chains */
    RendererChain *height_normal_chain;
    RendererChain *bloom_chain;
    RendererChain *tilt_chain;
    RendererChain *terrain_chain;
};

SceneTerrain::SceneTerrain(Canvas &pCanvas) :
    Scene(pCanvas, "terrain"), priv_(0)
{
    options_["repeat-overlay"] = Scene::Option("repeat-overlay", "6.0",
            "How many times to repeat the terrain texture on the terrain plane (per side)");
    options_["bloom"] = Scene::Option("bloom", "true",
                                      "Use bloom post-processing effect",
                                      "false,true");
    options_["tilt-shift"] = Scene::Option("tilt-shift", "true",
                                           "Use tilt-shift post-processing effect",
                                           "false,true");
}

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

bool
SceneTerrain::load()
{
    Scene::load();

    running_ = false;

    return true;
}

void
SceneTerrain::unload()
{
    Scene::unload();
}

void
SceneTerrain::setup()
{
    Scene::setup();

    /* Ensure implementation supports vertex texture fetch */
    GLint vertex_textures;
    glGetIntegerv(GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS, &vertex_textures);
    if (vertex_textures <= 0) {
        Log::error("SceneTerrain requires Vertex Texture Fetch support, "
                   "but GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS is %d\n",
                   vertex_textures);
        currentFrame_ = 0;
        startTime_ = Util::get_timestamp_us() / 1000000.0;
        running_ = false;
        return;
    }

    /* Parse options */
    float repeat = Util::fromString<double>(options_["repeat-overlay"].value);
    LibMatrix::vec2 repeat_overlay(repeat, repeat);
    bool use_bloom = options_["bloom"].value == "true";
    bool use_tilt_shift = options_["tilt-shift"].value == "true";

    priv_ = new SceneTerrainPrivate(canvas_, repeat_overlay,
                                    use_bloom, use_tilt_shift);

    /* Set up terrain rendering program */
    LibMatrix::Stack4 model;
    LibMatrix::Stack4 camera;
    LibMatrix::mat4 projection = LibMatrix::Mat4::perspective(
            40.0, canvas_.width() / static_cast<float>(canvas_.height()),
            2.0, 4000.0);

    /* Place camera */
    camera.lookAt(-1200.0f, 800.0f, 1200.0f,
                  0.0, 0.0, 0.0,
                  0.0, 1.0, 0.0);
    
    /* Move and rotate plane */
    model.translate(0.0f, -125.0f, 0.0f);
    model.rotate(-90.0, 1.0f, 0.0f, 0.0f);

    LibMatrix::mat4 view_matrix(camera.getCurrent());
    LibMatrix::mat4 model_matrix(model.getCurrent());

    LibMatrix::mat4 model_view_matrix(view_matrix * model_matrix);

    LibMatrix::mat4 normal_matrix(model_view_matrix);
    normal_matrix.inverse().transpose();

    /* Set up terrain renderer program */
    priv_->terrain_renderer->program().start();
    priv_->terrain_renderer->program()["viewMatrix"] = view_matrix;
    priv_->terrain_renderer->program()["modelViewMatrix"] = model_view_matrix;
    priv_->terrain_renderer->program()["normalMatrix"] = normal_matrix;
    priv_->terrain_renderer->program()["projectionMatrix"] = projection;

    /* Create the specular map */
    priv_->specular_map_renderer->render();

    glBindFramebuffer(GL_FRAMEBUFFER, 0);
    glViewport(0, 0, canvas_.width(), canvas_.height());

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

void
SceneTerrain::teardown()
{
    delete priv_;
    priv_ = 0;
    Scene::teardown();
}

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

    double now = Util::get_timestamp_us() / 1000000.0;
    float diff = now - startTime_;
    float scale = priv_->terrain_renderer->repeat_overlay().x() /
                  priv_->height_map_renderer->uv_scale().x();

    /* Update height map */
    priv_->height_map_renderer->program().start();
    priv_->height_map_renderer->program()["uvOffset"] = vec2(diff * 0.05f, 0.0f);
    priv_->terrain_renderer->program().start();
    priv_->terrain_renderer->program()["uOffset"] = vec2(scale * diff * 0.05f, 0.0f);
}

void
SceneTerrain::draw()
{
    /* Render the height and normal maps used by the terrain */
    priv_->height_normal_chain->render();

    /* Render the terrain plus any post-processing effects */
    priv_->terrain_chain->render();
}

Scene::ValidationResult
SceneTerrain::validate()
{
    return Scene::ValidationUnknown;
}
