/*
 *  Copyright (c) 2000-2022 Inria
 *  All rights reserved.
 *
 *  Redistribution and use in source and binary forms, with or without
 *  modification, are permitted provided that the following conditions are met:
 *
 *  * Redistributions of source code must retain the above copyright notice,
 *  this list of conditions and the following disclaimer.
 *  * Redistributions in binary form must reproduce the above copyright notice,
 *  this list of conditions and the following disclaimer in the documentation
 *  and/or other materials provided with the distribution.
 *  * Neither the name of the ALICE Project-Team nor the names of its
 *  contributors may be used to endorse or promote products derived from this
 *  software without specific prior written permission.
 * 
 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
 *  AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 *  IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
 *  ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
 *  LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 *  CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
 *  SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
 *  INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
 *  CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
 *  ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 *  POSSIBILITY OF SUCH DAMAGE.
 *
 *  Contact: Bruno Levy
 *
 *     https://www.inria.fr/fr/bruno-levy
 *
 *     Inria,
 *     Domaine de Voluceau,
 *     78150 Le Chesnay - Rocquencourt
 *     FRANCE
 *
 */

#include <geogram_gfx/gui/application.h>
#include <geogram_gfx/imgui_ext/imgui_ext.h>
#include <geogram_gfx/GLUP/GLUP.h>

// Demo for the Application class.
// Note: Application is the lowest level access to
//  geogram's application framework. It initializes
//  a window, OpenGL/GLUP and ImGui contexts.
// You can override draw_gui() and draw_graphics() to
//  draw your own stuff.
// Take a look at SimpleApplication / demo_SimpleApplication
//  for an easier-to-use baseclass.

namespace {
   using namespace GEO;

    // Point coordinates of the vertices of an icosahedron
    static double points[] = {
	0,          0.0,       1.175571,
	1.051462,   0.0,       0.5257311,
	0.3249197,  1.0,       0.5257311,
	-0.8506508, 0.618034,  0.5257311,
	-0.8506508, -0.618034, 0.5257311,
	0.3249197,  -1.0,      0.5257311,
	0.8506508,  0.618034,  -0.5257311,
	0.8506508,  -0.618034, -0.5257311,
	-0.3249197,  1.0,      -0.5257311,
	-1.051462,   0.0,      -0.5257311,
	-0.3249197, -1.0,      -0.5257311,
	0.0,         0.0,      -1.175571
    };

    // Facets of an icosahedron
    static index_t facets[] = {
	0,1,2,
	0,2,3,
	0,3,4,
	0,4,5,
	0,5,1,
	1,5,7,
	1,7,6,
	1,6,2,
	2,6,8,
	2,8,3,
	3,8,9,
	3,9,4,
	4,9,10,
	4,10,5,
	5,10,7,
	6,7,11,
	6,11,8,
	7,10,11,
	8,11,9,
	9,11,10,
    };

    
   class DemoApplication : public GEO::Application {
    public:
	DemoApplication() : GEO::Application(
	    "Geogram Demo App"
      )	{
	    demo_window_visible_ = false;
	    frame_ = 0;
	    // Call 'start_animation()' if you want draw_graphics() to be
	    // called continuously. Without it, draw_graphics() is only called
	    // when there is a gui event.
	    start_animation(); 
      }

    protected:
	void draw_gui() override {
	    // Draw the GUI of your application here, using ImGui.
	    if(demo_window_visible_) {
		ImGui::ShowDemoWindow(&demo_window_visible_);
	    }
	    ImGui::Begin("My window");
	    ImGui::Text("%s","Hello, world");

	    // To learn how to program a GUI element in ImGui, find
	    // it in the demo window, then look it up in the sources
	    // of ImGui (geogram_gfx/third_party/ImGui/imgui_demo.cpp)
	    ImGui::Checkbox("ImGui demo window", &demo_window_visible_);
	    ImGui::Checkbox("Animate", animate_ptr()); // Toggle animation
	    ImGui::End();
	}

	void draw_graphics() override {
	    // Draw the OpenGL graphic part of your application here.
	    Application::draw_graphics();
	    GLsizei L = GLsizei(std::min(get_width(), get_height()));
	    glViewport(0, 0, L, L);
	    glClearColor(0.1f, 0.1f, 0.1f, 1.0f);
	    glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	    glEnable(GL_DEPTH_TEST);


	    // GLUP has a re-implementation of the old fixed functionality
	    // pipeline (on top of modern OpenGL). It can be used to
	    // create simple geometry. For larger objects, use glupDrawArrays()
	    // and glupDrawElements()
	    glupMatrixMode(GLUP_MODELVIEW_MATRIX);
	    glupLoadIdentity();
	    glupScaled(0.7, 0.7, 0.7);
	    glupRotatef(float(frame_) * 0.3f, 1.0f, 1.0f, 1.0f);	    
	    glupSetColor3d(GLUP_FRONT_AND_BACK_COLOR, 0.0, 0.0, 0.0);
	    glupSetColor3d(GLUP_MESH_COLOR, 1.0, 1.0, 1.0);	    
	    glupEnable(GLUP_DRAW_MESH);
	    glupSetMeshWidth(3);
	    glupDisable(GLUP_LIGHTING);
	    glupBegin(GLUP_TRIANGLES);
	    for(index_t i=0; i<sizeof(facets) / sizeof(index_t); ++i) {
		index_t j = facets[i];
		glupVertex3dv(&points[3*j]);
	    }
	    glupEnd();

	    
	    if(animate()) {
		++frame_;
	    }
	}

       bool demo_window_visible_;
       index_t frame_;
   };
}

int main(int argc, char** argv) {
    DemoApplication app;
    app.start(argc, argv);
    return 0;
}
