/*
 * Copyright (c) 2019 Clementine Computing LLC.
 *
 * This file is part of PopuFare.
 * 
 * PopuFare is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Affero General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 * 
 * PopuFare 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 Affero General Public License for more details.
 * 
 * You should have received a copy of the GNU Affero General Public License
 * along with PopuFare.  If not, see <https://www.gnu.org/licenses/>.
 *
 */

//--------------------------------------- Menu Node related --------------------------------------

typedef enum 
{
    NODE_ROOT = 0, //this is special, respect its zero-ness
    NODE_MENU,	
    NODE_ACTION,
    NODE_WIDGET,
    NODE_CLASS,
    
    NUM_NODETYPES

} menunode_type;

extern char *nodetype_words[NUM_NODETYPES];

typedef enum 
{
    ACTION_RULE,
    
    ACTION_SETVAR,
    ACTION_APPEND,
    ACTION_BKSPACE,

    ACTION_SETMENU,
    ACTION_LOGIN,
    ACTION_LOGOUT,
    ACTION_SETPADDLE,
    ACTION_PREVSTOP,
    ACTION_NEXTSTOP,

    ACTION_SETEQNUM,
    ACTION_GETEQNUM,
    
    ACTION_CLRMSGS,

    ACTION_SHELLCALL,

    NUM_ACTIONS

} action_type;

extern char *action_words[NUM_ACTIONS];

typedef enum 
{
    WIDGET_MENUINIT = 0,	//not a real widget, just a placeholder for actions to take at menu init
    WIDGET_BUTTON,
    WIDGET_STATUSBAR,
    WIDGET_MESSAGES,
    WIDGET_INPUT,

    WIDGET_TEXT,
    WIDGET_BOX,
    WIDGET_FILLEDBOX,
    WIDGET_LINE,
    
    WIDGET_FULLSTATUS,
        
    NUM_WIDGETS

} widget_type;

extern char *widget_words[NUM_WIDGETS];

typedef enum
{
    FONT_SMALL = 0,
    FONT_MEDIUM,
    FONT_LARGE,
    
    NUM_FONTS

} widget_font;

extern char *font_words[NUM_FONTS];

#define WF_DONTDRAW	(0x0001)	//Don't draw this widget
#define WF_DISABLED	(0x0002)	//This widget is not clickabe (applies only to things like buttons that CAN be clickable)
#define WF_PRESSED	(0x0004)	//This widget is currently pressed (internal use only)
#define WF_SHADOW	(0x0008)	//This widget casts a shadow
#define WF_PASSWORD	(0x0010)	//This input widget is a password entry (echo * instead of data)

#define GRID		(16)

typedef struct widget_struct
{    
    int flags;
    
    widget_type type;		//What kind of a widget is this...

    int x, y, width, height;	//Coordinates and size in 16x16 grid units
    
    char *text;			//Text and font
    widget_font font;
    
    pixel color, bgcolor, textcolor, hotcolor;	//colors

} widget;


typedef struct action_struct
{
    action_type type;		//what kind of action is this
    
    //---------- common action params
    
    char *var;
    char *value;
    char *name;
    int limit;

} action;

typedef struct menu_struct
{
    int keys;
    char **key;
    char **value;
    
} menu;

typedef struct menunode_struct	//generic menu node structure
{
    menunode_type type;		//widget, action, or menu?
    
    struct menunode_struct *next;	//next item in list
    struct menunode_struct *subtree;	//subtree belonging to this item

    int keys;			//number of raw parameters
    
    char **key;			//raw keys
    char **value;		//raw values

    union			//data holders for this item (by type)
    {
        struct widget_struct	wid;
        struct action_struct	act;
        struct menu_struct	mnu;
    };

} menunode;

//--------------------------------------- Menu Variable related ----------------------------------

#define	MENUVAR_IDENTLEN	(16)
#define MENUVAR_VALUELEN	(32)

typedef struct menuvar_struct
{
    char ident[MENUVAR_IDENTLEN];
    char value[MENUVAR_VALUELEN];
    
    struct menuvar_struct *next;

} menuvar;

//--------------------------------------- Menu Tree related --------------------------------------

typedef struct menu_stack_struct
{
    menunode *n;
    menunode *tail;
    menunode_type expect;

} menu_stack;

#define PARSE_IN_CLASS_TAG	(1)

typedef struct menutree_struct
{
//--------------------------- These variables are used only during parse and initialization...
    unsigned int user_error;
    unsigned int parse_flags;
    unsigned int sp;
    XML_Parser parser;

    menu_stack stack[MENU_STACK_DEPTH];

//------------------------------  These variables are used duriong operation 

    //Head node of the menu tree (should contain all menus as children)
    struct menunode_struct *head;  

    //Currently active menu....
    struct menunode_struct *current;

    //Currently pressed button
    struct menunode_struct *pressed;
    //And its temporary flags
    int pressed_flags;
    
    //And touch state...
    int down;
    int down_x;
    int down_y;

//------------------------------

    struct menunode_struct *classlist;
    struct menuvar_struct *menuvars;

} menutree;

extern driver_status my_driver_status;
extern int update_driver_status;

extern time_t paddle_req_timeout;
extern set_paddle_req paddle_req;

//-------------------------------------------------------------------------------------

menutree *load_menutree(char *fname);
int init_menutree(menutree *mt);
void free_menutree(menutree *mt);
void print_menu_tree(menutree *mt);

int setmenu(menutree *mt, char *name);

int process_pen(menutree *mt, int x, int y, int down);
int draw_menu(menutree *mt);


void clear_diu_messages();
void add_diu_message(pixel bgcolor, pixel textcolor, char *message);
void replace_diu_message(pixel bgcolor, pixel textcolor, char *message);

int check_paddle_request(menutree *mt);
