#ifndef MENU_CPP
#define MENU_CPP

#include <SDL.h>
#include "sdl/SDL_gfx/SDL_framerate.h"

// See the comments on usage in menu.cpp

#define clear_surface(s) SDL_FillRect(s,NULL,0)

// Margin from the left border of menus for the start of text
#define HMARGIN 10

// SDL_gfx does its own mapping of colors and requires to be passed colors
// in this format...
#define mymakecol(r,g,b) (((r)<<24)|((g)<<16)|((b)<<8)|255)
#define makecol_alpha(r,g,b,a) (((r)<<24)|((g)<<16)|((b)<<8)|(a))
// converts a gfx to SDL_Color format :
#define gfx_to_sdlcolor(surf,c) SDL_MapRGBA(surf->format,(c)>>24,((c)>>16)&0xff,((c>>8)&0xff),(c)&0xff)

typedef struct {
                const char *label;
                int (*menu_func)(int);
                int     *value_int;
                int     values_list_size;
                int values_list[64];
                char* values_list_label[64];
} menu_item_t;

void sort_menu(menu_item_t *menu);
extern int emulate_mouse_cursor;
void setup_mouse_cursor(SDL_Surface *mycursor);
int add_menu_options(menu_item_t *menu);
void read_menu_config();
void save_menu_config();

/* Extensions to menu_items :
 * normally a menu_item is a string, with some other string options if
 * value_int != NULL.
 * Now I want some special widgets like progress bars. So if value_int != NULL
 * then if value_list_size > 0, it's a normal list of options
 * and if values_list_size < 0, it's an extension */

#define ITEM_NORMAL (0)
/* Progress bar : value_int must point to an integer with a value
 * from 0 to 100 */
#define ITEM_PROGRESS_BAR (-1)

#ifdef __cplusplus
#include "tfont.h"
#include "tlift.h"

/* If values_list_size == 3, and there are no labels for this list, then it's
 * a special interval list. Format { min, max, step }. It's an easy way to
 * allow big ranges of values */

// size of the key buffer to choose a menu entry by its label
#define MAX_KEYBUF 20

class TMenu {
  protected:
    const char *title;
    FPSmanager fpsm;
    menu_item_t *menu;
    // Index of the current selection or -1 if none, top = 1st index to be
    // displayed (in the menu_disp list now)
    int sel,top;
    int fg,bg, // colors for the fg layer
      bgsdl, // still bg color of the fg layer but in sdl format
      fg_frame,bg_frame, // colors for the frames (top & bottom)
      update_count;
    SDL_Rect work_area, // Area between the 2 frames
      fgdst, // area used by the fg layer (menu) on screen
      bgdst; // area used by the bg layer on screen (which can be different
      // from the work area because of the aspect ratio of the bg layer)
    int nb_items, // number of items in the menu (total)
      nb_disp_items, // number of items which can be displayed
      rows, // number of rows which can be displayed on screen
      width_max,exit_menu;
    int *menu_disp; // indexes of entries which can be displayed
    /* This array of indexes makes all the scrolling stuff much easier */
    int xoptions; // start x for the options (area on the right)
    int phase_repeat, timer, jmoved; // automatic repeat for joystick
    TFont *font;
    SDL_Surface *bg_layer, *fg_layer,*my_screen;
    int private_screen; // use a private screen to handle transparency ?
    TLift *lift; // in case a lift is needed !
    char keybuf[MAX_KEYBUF];
    int mousex[2],mousey[2],flip_page; // must handle the mouse when double buffering
  public:
    // There is a lot of methods, but most of them are very small and are
    // here to easily create objects which inherit from this one
    TMenu(char *my_title, menu_item_t *mymenu,char *myfont = NULL,
      int myfg=-1, int mybg=-1,int myfg_frame=-1,int mybg_frame=-1);
    virtual ~TMenu();
    virtual void draw_top_frame();
    virtual int get_max_bot_frame_dimensions(int &w, int &h);
    virtual void draw_bot_frame();
    virtual void draw_frame(SDL_Rect *r = NULL); // draw top & bottom frame, and sets the
    // work_area according to the size of the top & bottom frames.
    virtual void draw();
    virtual void adjust_len_max_options(unsigned int &len_max_options);
    virtual void setup_font(unsigned int len_frame);
    virtual void compute_width_from_font();
    virtual void setup_bg_layer(SDL_Surface *bitmap);
    virtual void setup_fg_layer();
    virtual void display_fglayer_header(int &y);
    virtual void skip_fglayer_header(int &y);
    virtual void update_fg_layer(int nb_to_update = -1);
    virtual void redraw_fg_layer();
    virtual void redraw(SDL_Rect *r);
    virtual void update_bg_layer(SDL_Rect *region);
    virtual void handle_key(SDL_Event *event);
    virtual void handle_mouse(SDL_Event *event);
    virtual void produce_joystick_event();
    virtual void handle_joystick(SDL_Event *event);
    virtual void exec_menu_item();
    virtual void  execute();
    virtual void do_update(SDL_Rect *region);
    virtual void compute_nb_items();
    virtual int compute_fglayer_height();
    // menu entries tests
    virtual int can_be_displayed(int n);
    virtual int can_be_selected(int n);
    int get_seldisp();
    void reset_top();
    virtual void next_sel();
    virtual void prev_sel();
    virtual void next_page();
    virtual void prev_page();
    virtual void goto_top();
    virtual void goto_end();
    virtual void find_new_sel();
    virtual void find_new_sel_from_end();
    virtual int compute_selcolor();
    virtual int get_fgcolor(int n) {
      return fg;
    }
    virtual void disp_menu(int n,int y,const char *s,int w,int h);
    virtual void prev_list_item();
    virtual void next_list_item();
    int get_list_index(int n);
    void set_title(char *my_title) {
      title = my_title;
    }
};

class TBitmap_menu : public TMenu {
  protected:
    SDL_Surface *bmp;
  public:
    TBitmap_menu(char *my_title, menu_item_t *mymenu, char *bitmap_path);
    ~TBitmap_menu();
    virtual void setup_font(unsigned int len_frame);
    virtual int compute_fglayer_height();
    virtual void display_fglayer_header(int &y);
    virtual void skip_fglayer_header(int &y);
};

class TDialog : public TMenu {
  protected:
    int htitle,use_bglayer;
  public:
    TDialog(char *my_title, menu_item_t *mymenu,int has_bglayer = 0) :
      TMenu(my_title,mymenu) { htitle = 0;
      use_bglayer = has_bglayer;
    }
    void setup_bg_layer(SDL_Surface *bitmap) {
      if (use_bglayer)
	TMenu::setup_bg_layer(bitmap);
    }
    void update_bg_layer(SDL_Rect *region) {
      if (use_bglayer) {
	TMenu::update_bg_layer(region);
      } 
    }
    virtual void setup_font(unsigned int len_frame);
    virtual int compute_fglayer_height();
    virtual void display_fglayer_header(int &y);
    virtual void skip_fglayer_header(int &y);
    virtual void draw_frame(SDL_Rect *r);
};

class TMenuMultiCol : public TMenu {
  protected:
    int *colpos;
    int nb_cols;
    char **cols;
  public:
    TMenuMultiCol(char *my_title, menu_item_t *mymenu, int nbcol, char **mycols);
    ~TMenuMultiCol();
    virtual void adjust_len_max_options(unsigned int &len_max_options);
    virtual void compute_width_from_font();
    virtual void disp_menu(int n,int y,const char *s,int w,int h);
};

#endif

#endif
