/*   Copyright 2005,2006 Paweł Niegowski
*
*    This file is part of Fenrir.
*
*    Fenrir is free software; you can redistribute it and/or modify
*    it under the terms of the GNU General Public License as published by
*    the Free Software Foundation; either version 2 of the License, or
*    (at your option) any later version.
*
*    Fenrir is distributed in the hope that it will be useful,
*    but WITHOUT ANY WARRANTY; without even the implied warranty of
*    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
*    GNU General Public License for more details.
*
*    You should have received a copy of the GNU General Public License
*    along with Fenrir; if not, write to the Free Software
*    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
*/

#ifndef GUI_H_INCLUDE
#define GUI_H_INCLUDE
#define GUI_MAX_TEXT 300

#define DIALOG_HP_DISPLAY 100
#define DIALOG_SKILL_DISPLAY 101
#define DIALOG_MENU_MENU 200
#define DIALOG_MENU_STAT 201
#define DIALOG_MENU_ITEM_UP 202
#define DIALOG_MENU_ITEM_DOWN 203
#define DIALOG_HOTKEY 300
#define DIALOG_LOOT 301

#define X_SPEED 6
#define Y_SPEED 5

#include <list>
#include "item.h"
using namespace std;

struct BITMAP;

class GUIElement
{
 public:
 GUIElement(int _x, int _y, int _w, int _h, int _dx, int _dy, int d);
 virtual ~GUIElement() {}
 virtual void think();
 virtual void draw() = 0;
 virtual void handle_keypress(int key) {}
 virtual void handle_packet(unsigned char *msg, int l) { }
 virtual int get_help_page() { return 0; }

 int x,y,w,h,dialog;
 //destination x, destination y, normal x and normal y - used for hide/unhide
 int dx,dy,nx,ny;
 bool remove;
 bool remove_at_dest;
 int x_speed,y_speed;
};

class GUIWindow : public GUIElement
{
 public:
 GUIWindow(int _x, int _y, int _w, int _h, int _dx, int _dy, int d, bool _fill = true);
 void think();
 void draw();

 int current_w,current_h,dest_w,dest_h;
 bool fill;
};

class GUIBar : public GUIElement
{
 public:
 GUIBar(int _x, int _y, int _w, int _dx, int _dy, int c, unsigned int *t, unsigned int m, int d);
 void think();
 void draw();

 int current_pos, dest_pos, color;
 unsigned int max;
 unsigned int *target;
};

class GUIText : public GUIElement
{
 public:
 GUIText(int _x, int _y, int _w, int _h, int _dx, int _dy, int c, char *t, int d);
 void think();
 void draw();

 char text[GUI_MAX_TEXT];
 int color;
};

class GUINumber : public GUIElement
{
 public:
 GUINumber(int _x, int _y, int _w, int _h, int _dx, int _dy, int c, unsigned int *t, int d);
 GUINumber(int _x, int _y, int _w, int _h, int _dx, int _dy, int c, unsigned short *t, int d);
 void think();
 void draw();
 int color;
 unsigned int *target_int;
 unsigned short *target_short;
};

class GUIImage : public GUIElement
{
 public:
 GUIImage(int _x, int _y, int _dx, int _dy, BITMAP *img, int d);
 void think();
 void draw();
 BITMAP *image;
};

struct _MenuElement
{
 char name[40];
 void (*func)();
};

class GUIMenu : public GUIElement
{
 public:
 GUIMenu(int _x, int _y, int _w,int _h, int _dx, int _dy, int d);
 void think();
 void draw();
 void add_element(char *name, void (*func)());
 void handle_keypress(int key);
 int get_help_page() { return 2; }
 list<_MenuElement> elements;
 list<_MenuElement>::iterator selection;
 bool selection_valid;
};

class GUIUpButton : public GUIElement
{
 public:
 GUIUpButton(GUINumber *t, bool (*cf)(GUINumber *t), void (*uf)(), GUIUpButton *p = 0);
 void think();
 void draw();
 void handle_keypress(int key);
 int get_help_page() { return 3; }
 bool (*check_func)(GUINumber *t);
 void (*up_func)();
 GUINumber *target;
 GUIUpButton *prev;
 GUIUpButton *next;
 int counter;
};

struct _AuraBubble
{
 _AuraBubble(float _v, int off)
 : h(0), v(_v), offset(off) { }
 float h, v;
 int offset;
};

class GUIAuraDisplay : public GUIElement
{
 public:
 GUIAuraDisplay(int _x, int _y, int _dx, int _dy, int d);
 void think();
 void draw();
 //mini particle system, indicating remaining energy
 list<_AuraBubble> bubbles_r, bubbles_g, bubbles_b;
};

class GUIItemList : public GUIElement
{
 public:
 GUIItemList(int _x, int _y, int _w, int _h, int _dx, int _dy, int d);
 void think();
 void draw();
 void handle_keypress(int key);
 int get_help_page() { return 4; }
};

class GUIItemDescription : public GUIElement
{
 public:
 GUIItemDescription(int _x, int _y, int _w, int _h, int _dx, int _dy, int d);
 void think();
 void draw();
};

class GUIHotkeySelection : public GUIElement
{
 public:
 GUIHotkeySelection(int _x, int _y, int _dx, int _dy, int d, GUIElement *p, unsigned char *pack, int pl);
 void think();
 void draw();
 void handle_keypress(int key);
 int get_help_page() { return 5; }

 int timer;
 int selection;
 GUIElement *parent;
 unsigned char packet[7];
 int plength;
};

class GUIHotkeyDelays : public GUIElement
{
 public:
 GUIHotkeyDelays(int _x, int _y, int _dx, int _dy, int d);
 void think();
 void draw();
};

struct _LootResult
{
 _LootResult(int _inv, unsigned short i, unsigned short _q)
 : id(i), q(_q), inv(_inv) {}
 _LootResult(const _LootResult &other)
 :id(other.id), q(other.q), inv(other.inv) {}
 unsigned short id, q;
 int inv;
};

class GUILootDialog : public GUIElement
{
 public:
 GUILootDialog(int _x, int _y, int _dx, int _dy, int d, unsigned short id, unsigned short quantity);
 void think();
 void draw();
 void handle_keypress(int key);
 void handle_packet(unsigned char *msg, int l);
 int get_help_page() { return 6; }
 unsigned short i,q,num;
 int timer;
 list<_LootResult> results;
};

extern GUIBar *hpbar, *mpbar;

void gui_init();
void gui_think();
void gui_draw();
void gui_cleanup();

void gui_handle_keypress(int key);
void gui_handle_packet(unsigned char *msg, int l);
int gui_get_help_page();

void gui_hide(int dialog_num, int dir, bool rem = false, int xspd = X_SPEED, int yspd = Y_SPEED);
void gui_unhide(int dialog_num);

void gui_test_dialog();
void gui_hp_display();
void gui_menu();
void gui_loadpalette();

#endif
