#include "wx/wx.h"
#include "wx/sizer.h"

#include "main.h"

// include OpenGL
#ifdef __WXMAC__
#include "OpenGL/gl.h"
#else
#include <GL/gl.h>
#endif

// this program sets up OpenGL to display a simple wireframe cube
// and close button in WxWidgets 2.7.x and later versions.
// 24 July, 2007 Marco Alfaro
// www.plot3d.net


IMPLEMENT_APP(MainApp)


bool MainApp::OnInit()
 {
    
  wxBoxSizer* sizer = new wxBoxSizer(wxHORIZONTAL);

   //set the initial window size
  int  width = 400;
  int  height = 200;

  MainFrame* MainWin  = new MainFrame("Hello world", wxPoint(1,1), wxSize(width,height) );
  MainWin->width = &width;
  MainWin->height = &height;
 
  int args[] = {WX_GL_RGBA, WX_GL_DOUBLEBUFFER, WX_GL_DEPTH_SIZE, 32, 0};
  MainWin->glWindow = new GLCanvas( MainWin,wxSize(width,height), args);
  MainWin->glWindow->SetCurrent(*MainWin->glWindow->MyContext);

  sizer->Add(MainWin->glWindow, 1, wxEXPAND);   
  MainWin->SetSizer(sizer);
  MainWin->SetAutoLayout(true);

  MainWin->Show(TRUE);
 
   return TRUE;
   
 }



BEGIN_EVENT_TABLE(MainFrame, wxFrame)
   EVT_SIZE(MainFrame::resized) 
   EVT_BUTTON  (BUTTON1, MainFrame::OnExit)
END_EVENT_TABLE()



BEGIN_EVENT_TABLE(GLCanvas, wxGLCanvas)
   EVT_ACTIVATE(GLCanvas::activate)
   EVT_PAINT(GLCanvas::paint) 
   EVT_ERASE_BACKGROUND(GLCanvas::OnEraseBackground)
END_EVENT_TABLE()



 MainFrame::MainFrame( const wxString& title, const wxPoint& pos, const wxSize& size):
        wxFrame(   (wxFrame*) NULL, -1, title, pos, size)
 {
       
  HelloWorld = new wxButton(this, BUTTON1, "close",wxDefaultPosition, wxDefaultSize,0);
         
 }



GLCanvas::GLCanvas(wxFrame* parent,const wxSize& size , int* args):wxGLCanvas(
parent,wxID_ANY,args,wxDefaultPosition,size,0,wxT("GLCanvas"),wxNullPalette)
 {
    
   MyContext = new wxGLContext(this,NULL);

 }


 void MainFrame::OnExit( wxCommandEvent& event )
 {
        
   Close(TRUE);
   
  }


 void GLCanvas::activate(wxActivateEvent& event)
 {

   prepare3DViewport();
  
 }


 void GLCanvas::paint(wxPaintEvent& event)
 {
        
   wxPaintDC(this);
   Render();
   SwapBuffers();

 }


void GLCanvas::OnEraseBackground( wxEraseEvent& WXUNUSED(event) )
{
    // empty function,to avoid flashing.
}


void MainFrame::resized(wxSizeEvent& event)
{

 GetClientSize( width, height);
 glViewport(0, 0, *width, *height); //reset viewport
 glWindow->SetSize(*width, *height );
 glWindow->aspect = *width/ *height;
 Refresh();

}



void GLCanvas::prepare3DViewport()
{
  
    //  Init the OpenGL viewport for drawing in 3D.
  
    glClearColor(0.0, 0.0, 0.0, 1.0); // a black background

    aspect = getWidth()/getHeight();


    float fov, znear, zfar, top, bottom, left, right;

    fov = 42;   
    znear = 0.3;
    zfar =200;
        
    top = tan(fov*M_PI/360.0) * znear;
    bottom = -top;
    left = aspect * bottom;
    right = aspect * top;
    glFrustum(left, right,bottom,top,znear,zfar);
  
    glMatrixMode(GL_MODELVIEW);
    glLoadIdentity();

}


 int MainFrame::getWidth()
{
    return GetSize().x;
}


int MainFrame::getHeight()
{
    return GetSize().y;
}


int GLCanvas::getWidth()
{
    return GetSize().x;
}


int GLCanvas::getHeight()
{
    return GetSize().y;
}



 void GLCanvas::Render()
{
 
 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 glLoadIdentity();
 
 //define the six planes of the cube
 double xmin, xmax, ymin, ymax, zmin, zmax;
 xmin =-0.5;
 xmax = 0.5;
 ymin = -0.5;
 ymax = 0.5;
 zmin =-0.5;
 zmax =0.5;

  
    glRotatef(25, 1.0, 0.0, 0.0);  //up and down

    glRotatef(35, 0.0, 1.0, 0.0);  //right and left

    glColor3d(1,1,0); //  yellow

     //draw a wireframe cube
    glBegin ( GL_LINES );
            

            glVertex3d(ymin,zmin,xmin);
            glVertex3d(ymin,zmin,xmax);
            
            glVertex3d(ymin,zmin,xmax);
            glVertex3d(ymax,zmin,xmax);
             
             glVertex3d(ymin,zmax,xmax);
             glVertex3d(ymax,zmax,xmax);

             glVertex3d(ymin,zmin,xmin);
             glVertex3d(ymax,zmin,xmin);

             glVertex3d(ymin,zmax,xmin);
             glVertex3d(ymax,zmax,xmin);

             glVertex3d(ymin,zmin,xmax);
             glVertex3d(ymin,zmax,xmax);

             glVertex3d(ymin,zmax,xmax);
             glVertex3d(ymin,zmax,xmin);

             glVertex3d(ymin,zmin,xmin);
             glVertex3d(ymin,zmax,xmin);
        
             glVertex3d(ymax,zmin,xmin);
             glVertex3d(ymax,zmin,xmax);

             glVertex3d(ymax,zmin,xmax);
             glVertex3d(ymax,zmax,xmax);

            glVertex3d(ymax,zmax,xmax);
            glVertex3d(ymax,zmax,xmin);

            glVertex3d(ymax,zmin,xmin);
            glVertex3d(ymax,zmax,xmin);

    glEnd();
   
}