#ifndef _MONITOR_H_INCLUDED_ 
#define _MONITOR_H_INCLUDED_ 
/////////////////////////////////////////////////////////////////////////////// 
// 
// Monitor.h 
// --------- 
// Curses based monitor interface definition 
// 
// Design and Implementation by Bjoern Lemke 
// 
// (C)opyright 2017 Bjoern Lemke 
// 
// INTERFACE MODULE 
// 
// Class: CegoAdmMon 
// 
// Description: Description: Cursor based monitor 
//
// Status: CLEAN 
// 
/////////////////////////////////////////////////////////////////////////////// 

#include <ctype.h> 
#include <string.h> 

#ifndef LFCNOCURSES

#ifdef HAVE_MINGW
#include <ncurses/ncurses.h>
#else
#include <ncurses.h>
#endif

#endif

#include "Chain.h" 
#include "ListT.h" 
#include "Datetime.h" 
#include "SigHandler.h" 

#define MON_TIMEOUT 0
#define MON_SELECT 1
#define MON_LEAVE 2

#define MON_RED 1
#define MON_GREEN 2
#define MON_YELLOW 3
#define MON_BLUE 4

#define DEFAULTATTRSEPTOKEN ":"
#define DEFAULTLISTSEPTOKEN ","
#define DEFAULTVALSEPTOKEN "="

class Monitor : public SigHandler { 

public: 

    class TableColor { 
    public: 
	TableColor() {};
	TableColor(const Chain& val)
	{
	    _val = val;
	    _code = 0;
	}
        TableColor(const Chain& val, int code) 
        { 
           _val = val; 
           _code = code; 
        }; 
        ~TableColor() {}; 
        const Chain& getValue() { return _val; }; 
        int getCode() { return _code; }; 
        TableColor& operator = (const TableColor& tc) 
        { 
           _val = tc._val; 
           _code = tc._code; 
           return(*this); 
        };

	bool operator == ( const TableColor& tc) const
	{
	    return _val == tc._val;
	};
	
    private: 
        Chain _val; 
        int _code; 
    }; 

    Monitor(const Chain& attrSepToken = DEFAULTATTRSEPTOKEN, const Chain& listSepToken = DEFAULTLISTSEPTOKEN, const Chain& valSepToken = DEFAULTVALSEPTOKEN); 
    ~Monitor(); 

    void regMenu(const Chain& name, int id);
    void regShortCut(char c, int code);

    // void regTableColor(const Chain& value, int colorCode); 

    int showHeader(); 
    void showInfoBox(const Chain& title, const Chain& msg, int width);
    int showFormBox(const Chain& title, const ListT<Chain>& attrList, ListT<Chain>& valList); 
    int showSelectBox(const Chain& title, const ListT<Chain>& selectList, int posx = 0, int posy = 0);

    int showAttributeBox(int keyLen, int valLen, const ListT< ListT<Chain> >& keyValueSpec, int timeout);

    int showTableBox(const Chain& title, ListT<Chain>& schema,  const ListT<ListT<Chain> >& table, int timeout, const ListT<TableColor>& colorMap, bool doInit = true, bool isSelectable = true);

    void setSelectedRow(int row);
    int getSelectedRow() const;


private: 

    class ShortCut { 
    public: 
        ShortCut() {}; 
        ShortCut(char c, int code) 
        { 
           _c = c; 
           _code = code; 
        }; 
        ~ShortCut() {}; 
        char getShortCut() { return _c; }; 
        int getCode() { return _code; }; 
        ShortCut& operator = (const ShortCut& sc) 
        { 
           _c = sc._c; 
           _code = sc._code; 
           return(*this); 
        }; 
    private: 
        char _c; 
        int _code; 
    };

    ListT<ShortCut> _scList; 

    class MenuItem { 
    public: 
        MenuItem() {}; 
        MenuItem(const Chain& name, int id) 
        { 
           _name = name; 
           _id = id; 
        }; 
        ~MenuItem() {}; 
        const Chain& getName() { return _name; }; 
        int getId() { return _id; }; 
        MenuItem& operator = (const MenuItem& mi) 
        { 
           _name = mi._name; 
           _id = mi._id; 
           return(*this); 
        }; 
    private: 
        Chain _name; 
        int _id; 
    }; 

    ListT<MenuItem> _menu;

    void sigCatch(int sig); 
    void refreshHeader();

    void getKeyValue(const Chain& s, Chain& key, Chain& value);
    void getAttrTypeValue(const Chain& s, Chain& attr, Chain& type, int& maxLen, Chain& value);
    void getListValue(const Chain& s, const Chain& key, Chain& value);
    void getListKey(const Chain& s, const Chain& value, Chain& key);

    void formatMsg(const Chain& msg, Chain& formatedMsg, int width, int& height);
    
    void nextCursorPos(int attrListSize, int curRow, int curCol, int& nextCurRow, int& nextCurCol); 
    void prevCursorPos(int attrListSize, int curRow, int curCol, int& prevCurRow, int& prevCurCol); 

    int _menuSelected; 

    int _rowSelected;
    Chain _attrSepToken;
    Chain _listSepToken;
    Chain _valSepToken;
   
#ifndef LFCNOCURSES
    void printMenu(WINDOW* win, const Chain& title, const ListT<Chain>& menuList, int highlight);
#endif 
    
}; 


#endif 
