/*         ______   ___    ___ 
 *        /\  _  \ /\_ \  /\_ \ 
 *        \ \ \L\ \\//\ \ \//\ \      __     __   _ __   ___ 
 *         \ \  __ \ \ \ \  \ \ \   /'__`\ /'_ `\/\`'__\/ __`\
 *          \ \ \/\ \ \_\ \_ \_\ \_/\  __//\ \L\ \ \ \//\ \L\ \
 *           \ \_\ \_\/\____\/\____\ \____\ \____ \ \_\\ \____/
 *            \/_/\/_/\/____/\/____/\/____/\/___L\ \/_/ \/___/
 *                                           /\____/
 *                                           \_/__/
 *
 *      Some definitions for internal use by the Windows library code.
 *
 *      By Stefan Schimanski.
 *
 *      See readme.txt for copyright information.
 */

#ifndef AINTWIN_H
#define AINTWIN_H

#ifndef ALLEGRO_H
   #error must include allegro.h first
#endif

#ifndef ALLEGRO_WINDOWS
   #error bad include
#endif


#include "allegro5/platform/aintwthr.h"
#include "allegro5/internal/aintern_display.h"
#include "allegro5/internal/aintern_system.h"
#include "allegro5/system_new.h"


#define WINDOWS_RGB(r,g,b)  ((COLORREF)(((BYTE)(r)|((WORD)((BYTE)(g))<<8))|(((DWORD)(BYTE)(b))<<16)))


AL_BEGIN_EXTERN_C


typedef struct ALLEGRO_DISPLAY_WIN ALLEGRO_DISPLAY_WIN;

struct ALLEGRO_DISPLAY_WIN
{
   ALLEGRO_DISPLAY display;

   HWND window;
   int mouse_range_x1;
   int mouse_range_y1;
   int mouse_range_x2;
   int mouse_range_y2;
   HCURSOR mouse_selected_hcursor;
   bool mouse_cursor_shown;
   /* used internally to disable the mouse when outside the window area */
   bool is_mouse_on;
   /* set to true if the user is browsing the system menu */
   bool is_in_sysmenu;

   UINT adapter;

   /*
    * The display thread must communicate with the main thread
    * through these variables.
    */
   volatile bool end_thread;    /* The display thread should end */
   volatile bool thread_ended;  /* The display thread has ended */
};


/* thread routines */
void _al_win_thread_init(void);
void _al_win_thread_exit(void);

/* input routines */
AL_FUNC(void, _al_win_input_init, (void));
AL_FUNC(void, _al_win_input_exit, (void));
bool _al_win_input_register_event(HANDLE event_id, void (*handler)(void));
bool _al_win_input_unregister_event(HANDLE event_id);
void _al_win_grab_input(ALLEGRO_DISPLAY_WIN *win_disp);

/* keyboard routines */
void _al_win_key_dinput_unacquire(void *unused);
void _al_win_key_dinput_grab(void *ALLEGRO_DISPLAY_WIN);

/* mouse routines */
void _al_win_mouse_dinput_grab(void *ALLEGRO_DISPLAY_WIN);
void _al_win_mouse_dinput_unacquire(void *win_disp);
void _al_win_mouse_set_sysmenu(bool state);

/* joystick routines */
void _al_win_joystick_dinput_unacquire(void *unused);
void _al_win_joystick_dinput_grab(void *ALLEGRO_DISPLAY_WIN);

/* custom Allegro messages */
extern UINT _al_win_msg_call_proc;
extern UINT _al_win_msg_suicide;

/* main window routines */
AL_FUNC(void, _al_win_wnd_schedule_proc, (HWND wnd, void (*proc)(void*), void *param));
AL_FUNC(void, _al_win_wnd_call_proc, (HWND wnd, void (*proc)(void*), void *param));

extern bool _al_win_disable_screensaver;

/* time */
void _al_win_init_time(void);
void _al_win_shutdown_time(void);

/* This is used to stop MinGW from complaining about type-punning */
#define MAKE_UNION(ptr, t) \
   union {                 \
      LPVOID *v;           \
      t p;                 \
   } u;                    \
   u.p = (ptr);

typedef struct ALLEGRO_SYSTEM_WIN ALLEGRO_SYSTEM_WIN;
/* This is our version of ALLEGRO_SYSTEM with driver specific extra data. */
struct ALLEGRO_SYSTEM_WIN
{
	ALLEGRO_SYSTEM system; /* This must be the first member, we "derive" from it. */
};

/* helpers to create windows */
HWND _al_win_create_window(ALLEGRO_DISPLAY *display, int width, int height, int flags);
HWND _al_win_create_faux_fullscreen_window(LPCTSTR devname, ALLEGRO_DISPLAY *display,
                                           int x1, int y1, int width, int height,
                                           int refresh_rate, int flags);
int  _al_win_init_window(void);
HWND _al_win_create_hidden_window(void);

/* icon helpers */
void  _al_win_set_display_icon(ALLEGRO_DISPLAY *display ,ALLEGRO_BITMAP *bitmap);
HICON _al_win_create_icon(HWND wnd, ALLEGRO_BITMAP *sprite, int xfocus, int yfocus, bool is_cursor);

/* window decorations */
void _al_win_set_window_position(HWND window, int x, int y);
void _al_win_get_window_position(HWND window, int *x, int *y);
void _al_win_toggle_window_frame(ALLEGRO_DISPLAY *display, HWND window, int w, int h, bool onoff);
void _al_win_set_window_title(ALLEGRO_DISPLAY *display, AL_CONST char *title);

/* cursor routines */
typedef struct ALLEGRO_MOUSE_CURSOR_WIN ALLEGRO_MOUSE_CURSOR_WIN;
struct ALLEGRO_MOUSE_CURSOR_WIN
{
   HCURSOR hcursor;
};

ALLEGRO_MOUSE_CURSOR* _al_win_create_mouse_cursor(ALLEGRO_DISPLAY *display, ALLEGRO_BITMAP *sprite, int xfocus, int yfocus);
void _al_win_destroy_mouse_cursor(ALLEGRO_DISPLAY *display, ALLEGRO_MOUSE_CURSOR *cursor);
bool _al_win_set_mouse_cursor(ALLEGRO_DISPLAY *display, ALLEGRO_MOUSE_CURSOR *cursor);
bool _al_win_set_system_mouse_cursor(ALLEGRO_DISPLAY *display, ALLEGRO_SYSTEM_MOUSE_CURSOR cursor_id);
bool _al_win_show_mouse_cursor(ALLEGRO_DISPLAY *display);
bool _al_win_hide_mouse_cursor(ALLEGRO_DISPLAY *display);


/* driver specific functions */

#if defined ALLEGRO_CFG_D3D
   ALLEGRO_DISPLAY_INTERFACE* _al_display_d3d_driver(void);
   int _al_d3d_get_num_display_modes(int format, int refresh_rate, int flags);
   ALLEGRO_DISPLAY_MODE* _al_d3d_get_display_mode(int index, int format,
                                                  int refresh_rate, int flags,
                                                  ALLEGRO_DISPLAY_MODE *mode);
   bool _al_d3d_init_display(void);
   int  _al_d3d_get_num_video_adapters(void);
   void _al_d3d_get_monitor_info(int adapter, ALLEGRO_MONITOR_INFO *info);
#endif /*  defined ALLEGRO_CFG_D3D */

#if defined ALLEGRO_CFG_OPENGL
   ALLEGRO_DISPLAY_INTERFACE *_al_display_wgl_driver(void);
   int _al_wgl_get_num_display_modes(int format, int refresh_rate, int flags);
   ALLEGRO_DISPLAY_MODE* _al_wgl_get_display_mode(int index, int format,
                                                  int refresh_rate, int flags,
                                                  ALLEGRO_DISPLAY_MODE *mode);
   bool _al_wgl_init_display(void);
   int  _al_wgl_get_num_video_adapters(void);
   void _al_wgl_get_monitor_info(int adapter, ALLEGRO_MONITOR_INFO *info);
#endif /*  defined ALLEGRO_CFG_OPENGL */


AL_END_EXTERN_C


#endif          /* !defined AINTWIN_H */

