//
// Copyright (c) 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//

//            Based on Simple_Texture2D.c from
// Book:      OpenGL(R) ES 2.0 Programming Guide
// Authors:   Aaftab Munshi, Dan Ginsburg, Dave Shreiner
// ISBN-10:   0321502795
// ISBN-13:   9780321502797
// Publisher: Addison-Wesley Professional
// URLs:      http://safari.informit.com/9780321563835
//            http://www.opengles-book.com

#include "SampleApplication.h"

#include "common/vector_utils.h"
#include "shader_utils.h"
#include "texture_utils.h"

#include <cstring>
#include <iostream>
#include <vector>

using namespace angle;

class SimpleInstancingSample : public SampleApplication
{
  public:
    SimpleInstancingSample()
        : SampleApplication("SimpleInstancing", 1280, 720)
    {
    }

    virtual bool initialize()
    {
        // init instancing functions
        char *extensionString = (char*)glGetString(GL_EXTENSIONS);
        if (strstr(extensionString, "GL_ANGLE_instanced_arrays"))
        {
            mVertexAttribDivisorANGLE = (PFNGLVERTEXATTRIBDIVISORANGLEPROC)eglGetProcAddress("glVertexAttribDivisorANGLE");
            mDrawArraysInstancedANGLE = (PFNGLDRAWARRAYSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawArraysInstancedANGLE");
            mDrawElementsInstancedANGLE = (PFNGLDRAWELEMENTSINSTANCEDANGLEPROC)eglGetProcAddress("glDrawElementsInstancedANGLE");
        }

        if (!mVertexAttribDivisorANGLE || !mDrawArraysInstancedANGLE || !mDrawElementsInstancedANGLE)
        {
            std::cerr << "Unable to load GL_ANGLE_instanced_arrays entry points.";
            return false;
        }

        const std::string vs = SHADER_SOURCE
        (
            attribute vec3 a_position;
            attribute vec2 a_texCoord;
            attribute vec3 a_instancePos;
            varying vec2 v_texCoord;
            void main()
            {
                gl_Position = vec4(a_position.xyz + a_instancePos.xyz, 1.0);
                v_texCoord = a_texCoord;
            }
        );

        const std::string fs = SHADER_SOURCE
        (
            precision mediump float;
            varying vec2 v_texCoord;
            uniform sampler2D s_texture;
            void main()
            {
                gl_FragColor = texture2D(s_texture, v_texCoord);
            }
        );

        mProgram = CompileProgram(vs, fs);
        if (!mProgram)
        {
            return false;
        }

        // Get the attribute locations
        mPositionLoc = glGetAttribLocation(mProgram, "a_position");
        mTexCoordLoc = glGetAttribLocation(mProgram, "a_texCoord");
        mInstancePosLoc = glGetAttribLocation(mProgram, "a_instancePos");

        // Get the sampler location
        mSamplerLoc = glGetUniformLocation(mProgram, "s_texture");

        // Load the texture
        mTextureID = CreateSimpleTexture2D();

        // Initialize the vertex and index vectors
        const GLfloat quadRadius = 0.01f;

        mVertices.push_back(Vector3(-quadRadius,  quadRadius, 0.0f));
        mVertices.push_back(Vector3(-quadRadius, -quadRadius, 0.0f));
        mVertices.push_back(Vector3( quadRadius, -quadRadius, 0.0f));
        mVertices.push_back(Vector3( quadRadius,  quadRadius, 0.0f));

        mTexcoords.push_back(Vector2(0.0f, 0.0f));
        mTexcoords.push_back(Vector2(0.0f, 1.0f));
        mTexcoords.push_back(Vector2(1.0f, 1.0f));
        mTexcoords.push_back(Vector2(1.0f, 0.0f));

        mIndices.push_back(0);
        mIndices.push_back(1);
        mIndices.push_back(2);
        mIndices.push_back(0);
        mIndices.push_back(2);
        mIndices.push_back(3);

        // Tile thousands of quad instances
        for (float y = -1.0f + quadRadius; y < 1.0f - quadRadius; y += quadRadius * 3)
        {
            for (float x = -1.0f + quadRadius; x < 1.0f - quadRadius; x += quadRadius * 3)
            {
                mInstances.push_back(Vector3(x, y, 0.0f));
            }
        }

        glClearColor(0.0f, 0.0f, 0.0f, 0.0f);

        return true;
    }

    virtual void destroy()
    {
        glDeleteProgram(mProgram);
        glDeleteTextures(1, &mTextureID);
    }

    virtual void draw()
    {
        // Set the viewport
        glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight());

        // Clear the color buffer
        glClear(GL_COLOR_BUFFER_BIT);

        // Use the program object
        glUseProgram(mProgram);

        // Load the vertex position
        glVertexAttribPointer(mPositionLoc, 3, GL_FLOAT, GL_FALSE, 0, mVertices.data());
        glEnableVertexAttribArray(mPositionLoc);

        // Load the texture coordinate
        glVertexAttribPointer(mTexCoordLoc, 2, GL_FLOAT, GL_FALSE, 0, mTexcoords.data());
        glEnableVertexAttribArray(mTexCoordLoc);

        // Load the instance position
        glVertexAttribPointer(mInstancePosLoc, 3, GL_FLOAT, GL_FALSE, 0, mInstances.data());
        glEnableVertexAttribArray(mInstancePosLoc);

        // Enable instancing
        mVertexAttribDivisorANGLE(mInstancePosLoc, 1);

        // Bind the texture
        glActiveTexture(GL_TEXTURE0);
        glBindTexture(GL_TEXTURE_2D, mTextureID);

        // Set the sampler texture unit to 0
        glUniform1i(mSamplerLoc, 0);

        // Do the instanced draw
        mDrawElementsInstancedANGLE(GL_TRIANGLES, static_cast<GLsizei>(mIndices.size()),
                                    GL_UNSIGNED_SHORT, mIndices.data(),
                                    static_cast<GLsizei>(mInstances.size()));
    }

  private:
    // Handle to a program object
    GLuint mProgram;

    // Attribute locations
    GLint mPositionLoc;
    GLint mTexCoordLoc;

    // Sampler location
    GLint mSamplerLoc;

    // Texture handle
    GLuint mTextureID;

    // Instance VBO
    GLint mInstancePosLoc;

    // Loaded entry points
    PFNGLVERTEXATTRIBDIVISORANGLEPROC mVertexAttribDivisorANGLE;
    PFNGLDRAWARRAYSINSTANCEDANGLEPROC mDrawArraysInstancedANGLE;
    PFNGLDRAWELEMENTSINSTANCEDANGLEPROC mDrawElementsInstancedANGLE;

    // Vertex data
    std::vector<Vector3> mVertices;
    std::vector<Vector2> mTexcoords;
    std::vector<Vector3> mInstances;
    std::vector<GLushort> mIndices;
};

int main(int argc, char **argv)
{
    SimpleInstancingSample app;
    return app.run();
}
