#pragma once
#include "appearance.h"
#include "notification.h"
#include <list>

enum SkinnableTypes { // for run-time type checking
	UnknownType,
	WindowType,
	ButtonType,
	ListBoxType,
	ListItemType,
	TextBoxType,
	CheckBoxType,
	DateBoxType,
	TimeBoxType,
	FrameType
};

// A convenience function for obtaining the type of 
// object connected with a given windows handle
SkinnableTypes GetType(HWND h);

class SkinnableWindow :
	public Appearance
{
public:
	SkinnableTypes type;
	SkinnableWindow(void);
	~SkinnableWindow(void);

	// Default Message Handlers
	virtual void Draw(Graphics& graphics);
	virtual void OnPaint(HWND hWnd, HDC hdc);
	virtual void OnMouseMove();
	virtual void OnMouseLeave();
	virtual void OnLButtonDown();
	virtual void OnLButtonUp();
	virtual void OnRButtonDown();
	virtual void OnRButtonUp();
	virtual void OnLButtonDblClk();
	virtual int OnChar(WPARAM wParam, LPARAM lParam);
	virtual void OnKeyDown(WPARAM wParam, LPARAM lParam);
	virtual void OnButton(HWND h);
	virtual void OnRightButton(HWND h);
	virtual void OnDblButton(HWND h);
	virtual void OnSize(int cx, int cy);
	virtual void OnMove(int x, int y);
	virtual void OnCarriageReturn(HWND h);
	virtual void OnGainFocus();
	virtual void OnLoseFocus();
	virtual void OnListSelect(HWND h, HWND hItem);
	virtual void OnListRightSelect(HWND h, HWND hItem);
	virtual void OnListDblSelect(HWND h, HWND hItem);
	virtual void OnListDeleteItem(WPARAM wParam, LPARAM lParam);
	virtual void OnButtonMove(HWND h);
	virtual void OnMouseEnter();
	virtual void OnMouseCaptureChanged();
	virtual int OnMeasureItem(MEASUREITEMSTRUCT * x);
	virtual int OnDrawItem(DRAWITEMSTRUCT * x);
	virtual int OnSetCursor(); // returns 1 if the cursor was changed, 0 otherwise
	virtual void OnScroll(HWND h);
	virtual void OnMouseWheel(float n); // scrolls n lines
	virtual void OnClose();
	virtual void OnDestroy();
	virtual void OnTimer();
	virtual void OnPopupStart(WPARAM wParam, LPARAM lParam);
	virtual void OnPopupEnd(WPARAM wParam, LPARAM lParam);
	virtual void OnContentsChanged(WPARAM wParam, LPARAM lParam);
	virtual void OnNotify(int idCtrl, NMHDR * pnmh);
	virtual void OnGeneric(WPARAM wParam, LPARAM lParam);
	virtual void Show();
	virtual void Hide();
	virtual void Enable();
	virtual void Disable();
	virtual bool Selected();
	void SetOpacity(float x);
	virtual void SetSize(int width, int height);
	void SetLocation(int x, int y);
	int Create(HWND parent = 0);
	static LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam);
	virtual void SetState(AppearanceState s);

	// Custom Notification
	static void PostNotify(int id, Notification& n);
	static void SendNotify(int id, Notification& n);
	static void SuspendAllCustomNotifications();
	static void ResumeAllCustomNotifications();
	static int AllNotificationsSuspended;
	static std::list<SkinnableWindow *> NotificationRecipients;

	// help balloons
	static void EnableHelpBalloons();
	static void DisableHelpBalloons();

	void AddCustomNotification(int id);
	void RemoveCustomNotification(int id);
	void RemoveAllCustomNotifications();
	int WantsNotify(int id);
	std::list<int> NotificationIds; // the registered notification ids for this window

	// context menu 
	HMENU hContextMenu;
	virtual int LoadContextMenu(UINT id);
	virtual LRESULT DisplayContextMenu();

	// the handler to be overridden by recipients
	virtual void OnCustomNotify(int id, Notification& n);

	// Data
	HWND hWnd;
	HWND hWndParent;

	std::wstring title;
	int pressable; // set to false if you want to override the pressed behavior
	int moveable; // set to false if you want the window to stay put
	int hidden;
	int MouseOutside; // true if the mouse is outside this window (used by WM_MOUSELEAVE)
	int ClipChildren;
	int ShowInTaskBar;

	void Redraw(void);

	// Tab order management
	virtual void SetTabTo(HWND h);
	virtual void SetTabFrom(HWND h);
	virtual HWND GetTabToTarget();
	virtual HWND GetTabFromTarget();
	HWND hTabTo, hTabFrom; // window to tab to

	std::list<Appearance *> visuals;

};

// messages for the SkinnableWindow's window procedure
#define ID_BASE_A				(WM_APP+100)
#define ID_LEFTBUTTON			(ID_BASE_A+1)
#define ID_CARRIAGERETURN		(ID_BASE_A+2)
#define ID_MINIMIZEBUTTON		(ID_BASE_A+3)
#define ID_LBSELECT				(ID_BASE_A+4)
#define ID_LBSELECT_RIGHT		(ID_BASE_A+5)
#define ID_LBSELECT_DBLCLK		(ID_BASE_A+6)
#define ID_BUTTONMOVE			(ID_BASE_A+7)
#define ID_SCROLLEVENT			(ID_BASE_A+8)
#define ID_TASKBAR				(ID_BASE_A+9)
#define ID_POPUPSTART			(ID_BASE_A+10)
#define ID_POPUPEND				(ID_BASE_A+11)
#define ID_CONTENTSCHANGED		(ID_BASE_A+12)
#define ID_LIST_DELETE			(ID_BASE_A+13)
#define ID_DOUBLEBUTTON			(ID_BASE_A+14)
#define ID_CUSTOMNOTIFY			(ID_BASE_A+15)
#define ID_GENERIC				(ID_BASE_A+16)
#define ID_RIGHTBUTTON			(ID_BASE_A+17)

#define ID_BASE_B				(ID_BASE_A+100)
#define ID_BASE_C				(ID_BASE_B+100)
#define ID_BASE_END				(ID_BASE_C+100)

#include "taborder.h"



