/* -----------------------------------------------------------------;
 * $source   : c:/ $
 * $revision : 1.0 $
 * $author   : root@null.co.za $
 * $date     : 2004/12/18 15:03:00 $
 * $desc     : $
 * $log      : $
 *
 * -----------------------------------------------------------------;
 */

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

c_app::c_app ( void ) {

   return;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

c_app::~c_app ( void ) {

   delete [] e_app;
   delete [] l_name;

   return;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

int c_app::m_init ( h_i l_hinst ) {

   e_conf->m_init (e_conf);

   l_name = (char*) malloc (sizeof(char));

   sprintf (l_name,  "%s",   e_conf->m_find ("name",   e_conf));
            l_width  = cint (e_conf->m_find ("width",  e_conf));
            l_height = cint (e_conf->m_find ("height", e_conf));
            l_bpp    = cint (e_conf->m_find ("bpp",    e_conf));
            l_full   = cint (e_conf->m_find ("full",   e_conf));

   e_app->l_hwnd = e_app->m_gui (e_app->l_width, e_app->l_height, 0, e_app->l_full, l_hinst);
   e_app->m_rect ();

   if (e_app->l_hwnd == NULL) { 
      e_err->m_set ("[error : (m_init)] [statement : (l_handle_creation_failure)],", e_err);
      exit (-1);
   }

   e_init->m_init ( );

   return 1;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

LRESULT CALLBACK c_app::m_proc ( h_w l_hwnd,
                                 u_i l_msg,
                                 p_w l_wparam,
                                 p_l l_lparam ) {
   long         l_ret = 0;
   p_s          l_ps;
   h_c          l_hdc;

   switch (l_msg) {
      case WM_COMMAND :
      case WM_LBUTTONDOWN :
      case WM_RBUTTONDOWN :
      case WM_MBUTTONDOWN :
      case WM_LBUTTONUP :
      case WM_RBUTTONUP :
      case WM_MBUTTONUP :
      case WM_MOUSEMOVE :
         e_inp->m_mouse_movement (l_lparam, l_msg);
         break;
      case WM_SIZE :
         if (!e_app->l_full) {
            e_app->m_resize (LOWORD (l_lparam), HIWORD (l_lparam));
            GetClientRect   (l_hwnd, &e_app->l_rect);
         }
         break;
      case WM_KEYDOWN :
         break;
      case WM_CLOSE :
         PostQuitMessage(false);
         break;

      default :
         l_ret = DefWindowProc (l_hwnd, l_msg, l_wparam, l_lparam);
         break;
   }
   return l_ret;  
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

int c_app::m_pixelformat ( h_c l_hdc,
                           int l_depth ) {

   PIXELFORMATDESCRIPTOR l_pfd;
   int                   l_pixelformat;

   l_pfd.nSize        = sizeof(PIXELFORMATDESCRIPTOR);
   l_pfd.nVersion     = 1;
   l_pfd.dwFlags      = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL | PFD_DOUBLEBUFFER;
   l_pfd.dwLayerMask  = PFD_MAIN_PLANE;
   l_pfd.iPixelType   = PFD_TYPE_RGBA;
   l_pfd.cColorBits   = l_depth;
   l_pfd.cDepthBits   = l_depth;
   l_pfd.cAccumBits   = 0;
   l_pfd.cStencilBits = 0;

   if((l_pixelformat = ChoosePixelFormat (l_hdc, &l_pfd)) == FALSE) {
      return false;
   }
 
   if(SetPixelFormat (l_hdc, l_pixelformat, &l_pfd) == FALSE) {
      return false;
   }
   return true;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

int c_app::m_fullscreen ( int l_x, int l_y ) {

   DEVMODE l_dm_settings;
   memset (&l_dm_settings, 0, sizeof(l_dm_settings)); 

   if(!EnumDisplaySettings (NULL, ENUM_CURRENT_SETTINGS, &l_dm_settings)) {
      return -1;
   }

   l_dm_settings.dmPelsWidth  = l_x;
   l_dm_settings.dmPelsHeight = l_y;
   l_dm_settings.dmFields     = DM_BITSPERPEL | DM_PELSWIDTH | DM_PELSHEIGHT;

   int r = ChangeDisplaySettings(&l_dm_settings, CDS_FULLSCREEN);

   if(r != DISP_CHANGE_SUCCESSFUL) {
      return -1;
   }
   return 1;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

void c_app::m_rect ( void ) {

   w_r	    l_rect;	

   GetClientRect (e_app->l_hwnd, &l_rect);
   e_app->l_width  = l_rect.right  - l_rect.left;
   e_app->l_height = l_rect.bottom - l_rect.top;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

void c_app::m_resize ( int l_x, int l_y ) {

}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

p_w c_app::m_loop ( void ) {

   w_m l_msg;

   while(true) {
      if (PeekMessage(&l_msg, NULL, 0, 0, PM_REMOVE)) {
         if (l_msg.message == WM_QUIT) break;
         TranslateMessage (&l_msg);
         DispatchMessage  (&l_msg);
      }else{
         e_render->m_render();
      }
   }
   
   return l_msg.wParam;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

int c_app::m_exit ( void ) {

   if (e_app->l_hdc) {
      ReleaseDC             (e_app->l_hwnd, e_app->l_hdc);
   }
   if (e_app->l_full) {
      ChangeDisplaySettings (NULL, 0);
      ShowCursor            (TRUE);
   }

   cgD3D9SetDevice     ( NULL );
   cgDestroyProgram    ( e_d3d->l_cg_program );
   cgDestroyContext    ( e_d3d->l_cg_context );
	
   m_safe_release      ( e_d3d->l_aniso_lookup );
   m_safe_release      ( e_d3d->l_vertex_buffer );
   m_safe_release      ( e_d3d->l_index_buffer );
   m_safe_delete_array ( e_d3d->l_attributes );
   m_safe_release      ( e_d3d->l_d3d_device );
   m_safe_release      ( e_d3d->l_d3d );

   UnregisterClass (e_app->l_name, e_app->l_hinst);

   return true;
}

//------------------------------------------------------------------;
//
//------------------------------------------------------------------;

h_w c_app::m_gui ( int       l_x,
                   int       l_y,
                   d_w       l_style,
                   int       l_full,
                   h_i       l_hinst ) {

   h_w l_wnd;
   w_c l_wnd_class;

   memset (&l_wnd_class, 0, sizeof(WNDCLASS));

   l_wnd_class.style         = CS_HREDRAW | CS_VREDRAW;
   l_wnd_class.lpfnWndProc   = e_app->m_proc;
   l_wnd_class.hInstance     = l_hinst;
   l_wnd_class.hIcon         = LoadIcon  (NULL, IDI_APPLICATION);
   l_wnd_class.hCursor       = LoadCursor(NULL, IDC_ARROW);
   l_wnd_class.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
   l_wnd_class.lpszMenuName  = e_app->l_name;
   l_wnd_class.lpszClassName = e_app->l_name;

   RegisterClass (&l_wnd_class);

   if(l_full && !l_style) {
      l_style = WS_POPUP | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
      m_fullscreen (e_app->l_width, e_app->l_height);
   }else
   if(!l_style) {
//    l_style =  WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN | WS_MAXIMIZE;
      l_style =  WS_OVERLAPPEDWINDOW | WS_CLIPSIBLINGS | WS_CLIPCHILDREN;
   }

   e_app->l_hinst = l_hinst;

   w_r l_window;
   l_window.left   = 0;
   l_window.right  = l_x;
   l_window.top    = 0;
   l_window.bottom = l_y;

   AdjustWindowRect (&l_window, l_style, false);

   l_wnd = CreateWindow (e_app->l_name,
                         e_app->l_name,
                         l_style,
                         0, 0,  
                         l_window.right  - l_window.left,
                         l_window.bottom - l_window.top,
                         NULL,
                         NULL,
                         l_hinst,
                         NULL);
   if(!l_wnd) {
      e_err->m_set ("[error : (m_gui)] [statement : (l_window_creation_failure)]", e_err);
      exit (-1);
      return NULL;
   }

   ShowWindow   (l_wnd, SW_SHOWNORMAL); // SW_SHOWNORMAL, SW_MAXIMIZE
   UpdateWindow (l_wnd);
   SetFocus     (l_wnd);

   return        l_wnd;
}
