// objects.h - Base classes for object manager of GUI

#ifndef _OBJECTS_HEADER
#define _OBJECTS_HEADER

#include "rapidxml.hpp"
#include <vector>
#include <string>
#include <map>

extern "C" {
#include "../minzip/Zip.h"
}

using namespace rapidxml;

#include "../data.hpp"
#include "resources.hpp"
#include "pages.hpp"

class RenderObject
{
public:
    enum Placement {
        TOP_LEFT = 0,
        TOP_RIGHT = 1,
        BOTTOM_LEFT = 2,
        BOTTOM_RIGHT = 3,
        CENTER = 4,
		CENTER_X_ONLY = 5,
    };

public:
    RenderObject()              { mRenderX = 0; mRenderY = 0; mRenderW = 0; mRenderH = 0; mPlacement = TOP_LEFT; }
    virtual ~RenderObject()     {}

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void) = 0;

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void)        { return 0; }

    // GetRenderPos - Returns the current position of the object
    virtual int GetRenderPos(int& x, int& y, int& w, int& h)        { x = mRenderX; y = mRenderY; w = mRenderW; h = mRenderH; return 0; }

    // SetRenderPos - Update the position of the object
    //  Return 0 on success, <0 on error
    virtual int SetRenderPos(int x, int y, int w = 0, int h = 0)    { mRenderX = x; mRenderY = y; if (w || h) { mRenderW = w; mRenderH = h; } return 0; }

    // GetPlacement - Returns the current placement
    virtual int GetPlacement(Placement& placement)                  { placement = mPlacement; return 0; }

    // SetPlacement - Update the current placement
    virtual int SetPlacement(Placement placement)                   { mPlacement = placement; return 0; }

    // SetPageFocus - Notify when a page gains or loses focus
    virtual void SetPageFocus(int inFocus)                          { return; }

protected:
    int mRenderX, mRenderY, mRenderW, mRenderH;
    Placement mPlacement;
};

class ActionObject
{
public:
    ActionObject()              { mActionX = 0; mActionY = 0; mActionW = 0; mActionH = 0; }
    virtual ~ActionObject()     {}

public:
    // NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y)        { return 0; }

    // NotifyKey - Notify of a key press
    //  Return 0 on success (and consume key), >0 to pass key to next handler, and <0 on error
    virtual int NotifyKey(int key)                                  { return 1; }

    // GetRenderPos - Returns the current position of the object
    virtual int GetActionPos(int& x, int& y, int& w, int& h)        { x = mActionX; y = mActionY; w = mActionW; h = mActionH; return 0; }

    // SetRenderPos - Update the position of the object
    //  Return 0 on success, <0 on error
    virtual int SetActionPos(int x, int y, int w = 0, int h = 0);

    // IsInRegion - Checks if the request is handled by this object
    //  Return 0 if this object handles the request, 1 if not
    virtual int IsInRegion(int x, int y)                            { return ((x < mActionX || x > mActionX + mActionW || y < mActionY || y > mActionY + mActionH) ? 0 : 1); }

    // NotifyVarChange - Notify of a variable change
    //  Returns 0 on success, <0 on error
    virtual int NotifyVarChange(std::string varName, std::string value)     { return 0; }

protected:
    int mActionX, mActionY, mActionW, mActionH;
};

class Conditional
{
public:
    Conditional(xml_node<>* node);

public:
    bool IsConditionVariable(std::string var);
    bool isConditionTrue();
    bool isConditionValid();
    void NotifyPageSet();

protected:
    class Condition
    {
    public:
        std::string mVar1;
        std::string mVar2;
        std::string mCompareOp;
        std::string mLastVal;
    };

    std::vector<Condition> mConditions;

protected:
    bool isMounted(std::string vol);
    bool isConditionTrue(Condition* condition);

};

class InputObject
{
public:
    InputObject()              { HasInputFocus = 0; }
    virtual ~InputObject()     {}

public:
    // NotifyKeyboard - Notify of keyboard input
    //  Return 0 on success (and consume key), >0 to pass key to next handler, and <0 on error
    virtual int NotifyKeyboard(int key)                                  { return 1; }

	virtual int SetInputFocus(int focus)    { HasInputFocus = focus; return 1; }

protected:
	int HasInputFocus;
};

// Derived Objects
// GUIText - Used for static text
class GUIText : public RenderObject, public ActionObject, public Conditional

{
public:
    // w and h may be ignored, in which case, no bounding box is applied
    GUIText(xml_node<>* node);

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // Retrieve the size of the current string (dynamic strings may change per call)
    virtual int GetCurrentBounds(int& w, int& h);

    // Notify of a variable change
    virtual int NotifyVarChange(std::string varName, std::string value);

	// Set maximum width in pixels
	virtual int SetMaxWidth(unsigned width);

	// Set number of characters to skip (for scrolling)
	virtual int SkipCharCount(unsigned skip);

protected:
    std::string mText;
    std::string mLastValue;
    COLOR mColor;
    Resource* mFont;
    int mIsStatic;
    int mVarChanged;
    int mFontHeight;
	unsigned maxWidth;
	unsigned charSkip;

protected:
    std::string parseText(void);
};

// GUIImage - Used for static image
class GUIImage : public RenderObject
{
public:
    GUIImage(xml_node<>* node);

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // SetRenderPos - Update the position of the object
    //  Return 0 on success, <0 on error
    virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);

protected:
    Resource* mImage;
};

// GUIFill - Used for fill colors
class GUIFill : public RenderObject
{
public:
    GUIFill(xml_node<>* node);

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

protected:
    COLOR mColor;
};

// GUIAction - Used for standard actions
class GUIAction : public ActionObject, public Conditional
{
public:
    GUIAction(xml_node<>* node);

public:
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
    virtual int NotifyKey(int key);
    virtual int NotifyVarChange(std::string varName, std::string value);
	virtual int doActions();

protected:
    class Action
    {
    public:
        std::string mFunction;
        std::string mArg;
    };

    std::vector<Action> mActions;
    int mKey;

protected:
    int getKeyByName(std::string key);
    virtual int doAction(Action action, int isThreaded = 0);
    static void* thread_start(void *cookie);
	void simulate_progress_bar(void);
    int flash_zip(std::string filename, std::string pageName, const int simulate, int* wipe_cache);
	void operation_start(const string operation_name);
	void operation_end(const int operation_status, const int simulate);
	static void* command_thread(void *cookie);
};

class GUIConsole : public RenderObject, public ActionObject
{
public:
    GUIConsole(xml_node<>* node);

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // SetRenderPos - Update the position of the object
    //  Return 0 on success, <0 on error
    virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);

    // IsInRegion - Checks if the request is handled by this object
    //  Return 0 if this object handles the request, 1 if not
    virtual int IsInRegion(int x, int y);

    // NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error (Return error to allow other handlers)
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);

protected:
    enum SlideoutState
    {
        hidden = 0,
        visible,
        request_hide,
        request_show
    };
    Resource* mFont;
    Resource* mSlideoutImage;
    COLOR mForegroundColor;
    COLOR mBackgroundColor;
    COLOR mScrollColor;
    unsigned int mFontHeight;
    int mCurrentLine;
    unsigned int mLastCount;
    unsigned int mMaxRows;
    int mStartY;
    int mSlideoutX, mSlideoutY, mSlideoutW, mSlideoutH;
    int mSlideinX, mSlideinY, mSlideinW, mSlideinH;
    int mConsoleX, mConsoleY, mConsoleW, mConsoleH;
    int mLastTouchX, mLastTouchY;
    int mSlideMultiplier;
    int mSlideout;
    SlideoutState mSlideoutState;

protected:
    virtual int RenderSlideout(void);
    virtual int RenderConsole(void);

};

class GUIButton : public RenderObject, public ActionObject, public Conditional
{
public:
    GUIButton(xml_node<>* node);
    virtual ~GUIButton();

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // SetPos - Update the position of the render object
    //  Return 0 on success, <0 on error
    virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);

    // NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);

protected:
    GUIImage* mButtonImg;
    Resource* mButtonIcon;
    GUIText* mButtonLabel;
    GUIAction* mAction;
    int mTextX, mTextY, mTextW, mTextH;
    int mIconX, mIconY, mIconW, mIconH;
    bool mRendered;
};

class GUICheckbox: public RenderObject, public ActionObject, public Conditional
{
public:
    GUICheckbox(xml_node<>* node);
    virtual ~GUICheckbox();

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // SetPos - Update the position of the render object
    //  Return 0 on success, <0 on error
    virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);

    // NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);

protected:
    Resource* mChecked;
    Resource* mUnchecked;
    GUIText* mLabel;
    int mTextX, mTextY;
    int mCheckX, mCheckY, mCheckW, mCheckH;
    int mLastState;
    bool mRendered;
    std::string mVarName;
};

class GUIFileSelector : public RenderObject, public ActionObject
{
public:
    GUIFileSelector(xml_node<>* node);
    virtual ~GUIFileSelector();

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);

    // NotifyVarChange - Notify of a variable change
    virtual int NotifyVarChange(std::string varName, std::string value);

    // SetPos - Update the position of the render object
    //  Return 0 on success, <0 on error
    virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);

    // SetPageFocus - Notify when a page gains or loses focus
    virtual void SetPageFocus(int inFocus);

protected:
    struct FileData {
        std::string fileName;
        unsigned char fileType;     // Uses d_type format from struct dirent
        mode_t protection;          // Uses mode_t format from stat
        uid_t userId;
        gid_t groupId;
        off_t fileSize;
        time_t lastAccess;          // Uses time_t format from stat
        time_t lastModified;        // Uses time_t format from stat
        time_t lastStatChange;      // Uses time_t format from stat
    };

protected:
    virtual int GetSelection(int x, int y);

    virtual int GetFileList(const std::string folder);
    static bool fileSort(FileData d1, FileData d2);

protected:
    std::vector<FileData> mFolderList;
    std::vector<FileData> mFileList;
    std::string mPathVar;
    std::string mExtn;
    std::string mVariable;
	std::string mSortVariable;
	std::string mSelection;
	std::string mHeaderText;
	std::string mLastValue;
    int actualLineHeight;
	int mStart;
    int mLineSpacing;
	int mSeparatorH;
	int mHeaderSeparatorH;
    int mShowFolders, mShowFiles, mShowNavFolders;
    int mUpdate;
    int mBackgroundX, mBackgroundY, mBackgroundW, mBackgroundH;
	int mHeaderH;
	static int mSortOrder;
	int startY;
	int scrollingSpeed;
	int scrollingY;
	int mHeaderIsStatic;
	int touchDebounce;
    unsigned mFontHeight;
    unsigned mLineHeight;
    int mIconWidth, mIconHeight, mFolderIconHeight, mFileIconHeight, mFolderIconWidth, mFileIconWidth, mHeaderIconHeight, mHeaderIconWidth;
    Resource* mHeaderIcon;
	Resource* mFolderIcon;
    Resource* mFileIcon;
    Resource* mBackground;
    Resource* mFont;
    COLOR mBackgroundColor;
    COLOR mFontColor;
	COLOR mHeaderBackgroundColor;
	COLOR mHeaderFontColor;
	COLOR mSeparatorColor;
	COLOR mHeaderSeparatorColor;
};

class GUIListBox : public RenderObject, public ActionObject
{
public:
    GUIListBox(xml_node<>* node);
    virtual ~GUIListBox();

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);

    // NotifyVarChange - Notify of a variable change
    virtual int NotifyVarChange(std::string varName, std::string value);

    // SetPos - Update the position of the render object
    //  Return 0 on success, <0 on error
    virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);

    // SetPageFocus - Notify when a page gains or loses focus
    virtual void SetPageFocus(int inFocus);

protected:
    struct ListData {
        std::string displayName;
		std::string variableValue;
		unsigned int selected;
    };

protected:
    virtual int GetSelection(int x, int y);

protected:
    std::vector<ListData> mList;
    std::string mVariable;
	std::string mSelection;
	std::string currentValue;
    int mStart;
    int mLineSpacing;
    int mUpdate;
    int mBackgroundX, mBackgroundY, mBackgroundW, mBackgroundH;
	static int mSortOrder;
    unsigned mFontHeight;
    unsigned mLineHeight;
    int mIconWidth, mIconHeight;
    Resource* mIconSelected;
    Resource* mIconUnselected;
    Resource* mBackground;
    Resource* mFont;
    COLOR mBackgroundColor;
    COLOR mFontColor;
};

// GUIAnimation - Used for animations
class GUIAnimation : public RenderObject
{
public:
    GUIAnimation(xml_node<>* node);

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

protected:
    AnimationResource* mAnimation;
    int mFrame;
    int mFPS;
    int mLoop;
    int mRender;
    int mUpdateCount;
};

class GUIProgressBar : public RenderObject, public ActionObject
{
public:
    GUIProgressBar(xml_node<>* node);

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // NotifyVarChange - Notify of a variable change
    //  Returns 0 on success, <0 on error
    virtual int NotifyVarChange(std::string varName, std::string value);

protected:
    Resource* mEmptyBar;
    Resource* mFullBar;
    std::string mMinValVar;
    std::string mMaxValVar;
    std::string mCurValVar;
    float mSlide;
    float mSlideInc;
    int mSlideFrames;
    int mLastPos;

protected:
    virtual int RenderInternal(void);       // Does the actual render

};

class GUISlider : public RenderObject, public ActionObject
{
public:
    GUISlider(xml_node<>* node);
    virtual ~GUISlider();

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);

protected:
    GUIAction* sAction;
    Resource* sSlider;
    Resource* sSliderUsed;
    Resource* sTouch;
    int sTouchW, sTouchH;
    int sCurTouchX;
    int sUpdate;
};

#define MAX_KEYBOARD_LAYOUTS 5
#define MAX_KEYBOARD_ROWS 9
#define MAX_KEYBOARD_KEYS 20
#define KEYBOARD_ACTION 253
#define KEYBOARD_LAYOUT 254
#define KEYBOARD_SWIPE_LEFT 252
#define KEYBOARD_SWIPE_RIGHT 251
#define KEYBOARD_ARROW_LEFT 250
#define KEYBOARD_ARROW_RIGHT 249
#define KEYBOARD_HOME 248
#define KEYBOARD_END 247
#define KEYBOARD_ARROW_UP 246
#define KEYBOARD_ARROW_DOWN 245
#define KEYBOARD_SPECIAL_KEYS 245
#define KEYBOARD_BACKSPACE 8

class GUIKeyboard : public RenderObject, public ActionObject, public Conditional
{
public:
	GUIKeyboard(xml_node<>* node);
    virtual ~GUIKeyboard();

public:
	virtual int Render(void);
	virtual int Update(void);
	virtual int NotifyTouch(TOUCH_STATE state, int x, int y);
	virtual int SetRenderPos(int x, int y, int w = 0, int h = 0);

protected:
	virtual int GetSelection(int x, int y);

protected:
	struct keyboard_key_class
    {
        unsigned char key;
		unsigned char longpresskey;
        unsigned int end_x;
		unsigned int layout;
    };

	Resource* keyboardImg[MAX_KEYBOARD_LAYOUTS];
	struct keyboard_key_class keyboard_keys[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS][MAX_KEYBOARD_KEYS];
	bool mRendered;
	std::string mVariable;
	unsigned int cursorLocation;
	unsigned int currentLayout;
	unsigned int row_heights[MAX_KEYBOARD_LAYOUTS][MAX_KEYBOARD_ROWS];
	unsigned int KeyboardWidth, KeyboardHeight;
	GUIAction* mAction;
};

// GUIInput - Used for keyboard input
class GUIInput : public RenderObject, public ActionObject, public Conditional, public InputObject
{
public:
    // w and h may be ignored, in which case, no bounding box is applied
    GUIInput(xml_node<>* node);
	virtual ~GUIInput();

public:
    // Render - Render the full object to the GL surface
    //  Return 0 on success, <0 on error
    virtual int Render(void);

    // Update - Update any UI component animations (called <= 30 FPS)
    //  Return 0 if nothing to update, 1 on success and contiue, >1 if full render required, and <0 on error
    virtual int Update(void);

    // Notify of a variable change
    virtual int NotifyVarChange(std::string varName, std::string value);

	// NotifyTouch - Notify of a touch event
    //  Return 0 on success, >0 to ignore remainder of touch, and <0 on error
    virtual int NotifyTouch(TOUCH_STATE state, int x, int y);

	virtual int NotifyKeyboard(int key);

protected:
	virtual int GetSelection(int x, int y);

	// Handles displaying the text properly when chars are added, deleted, or for scrolling
	virtual int HandleTextLocation(int x);

protected:
    GUIText* mInputText;
	GUIAction* mAction;
	Resource* mBackground;
	Resource* mCursor;
	Resource* mFont;
	std::string mText;
    std::string mLastValue;
	std::string mVariable;
	std::string mMask;
	std::string mMaskVariable;
    COLOR mBackgroundColor;
	COLOR mCursorColor;
	int scrollingX;
	int lastX;
	int mCursorLocation;
	int mBackgroundX, mBackgroundY, mBackgroundW, mBackgroundH;
	int mFontY;
	unsigned skipChars;
	unsigned mFontHeight;
	unsigned CursorWidth;
	bool mRendered;
	bool HasMask;
	bool DrawCursor;
	bool isLocalChange;
	bool HasAllowed;
	bool HasDisabled;
	std::string AllowedList;
	std::string DisabledList;
	unsigned MinLen;
	unsigned MaxLen;
};

class HardwareKeyboard
{
public:
	HardwareKeyboard(void);
	virtual ~HardwareKeyboard();

public:
	virtual int KeyDown(int key_code);
	virtual int KeyUp(int key_code);
	virtual int KeyRepeat(void);
};

// Helper APIs
bool LoadPlacement(xml_node<>* node, int* x, int* y, int* w = NULL, int* h = NULL, RenderObject::Placement* placement = NULL);

#endif  // _OBJECTS_HEADER

