#ifndef __Task__H
#define __Task__H

#include "std.h"
#include <stdarg.h>

#include "coords.h"
#include "kernel.h"

#include <stdbool.h>
#include "WimpLib:EventSender.h"
#include "WimpLib:Event.h"
#include "WimpLib:Sprites.h"
#include "WimpLib:JobList.h"

#ifdef __cplusplus
extern "C" {
#endif

typedef struct
{
	int   shiftx; // Number of bits to shift right OS x to get screen pixel
	int   shifty; // Number of bits to shift right OS y to get screen pixel
	int   dx;     // OS x units per screen pixel
	int   dy;     // OS y units per screen pixel
	int   bpp;    // bits per screen pixel
	int   resx;   // OS x units per inch
	int   resy;   // OS y units per inch
	int   millix; // OS x to millipoints
	int   milliy; // OS y to millipoints
	CRect box;    // Screen box
} Mode_Info;

// Constructor and destructor
void throw_Task_Task(bool cpp, int version, const char* pTaskName, const char* pTaskSprite, const char* pTaskDir, int* pMsgList);
void Task_NotTask(int retval);

#define EPollMask_Null            0x00000001
#define EPollMask_WindowRedraw    0x00000002
#define EPollMask_WindowOpen      0x00000004
#define EPollMask_WindowClose     0x00000008
#define EPollMask_WindowPtrLeave  0x00000010
#define EPollMask_WindowPtrEnter  0x00000020
#define EPollMask_Mouse           0x00000040
#define EPollMask_Drag            0x00000080
#define EPollMask_Key             0x00000100
#define EPollMask_Menu            0x00000200
#define EPollMask_WindowScroll    0x00000400
#define EPollMask_WindowLoseCaret 0x00000800
#define EPollMask_WindowGainCaret 0x00001000
#define EPollMask_PollWord        0x00002000
#define EPollMask_Message         (1 << 17)
#define EPollMask_MessageWantAck  (1 << 18)
#define EPollMask_MessageAck      (1 << 19)

// Wimp_PollIdle handling
void Task_MainLoop(unsigned int mask, int time_step);
Event* Task_PollIdle(unsigned int mask, int time_step);
void Task_ProcessEvent(const Event* pe);
void Task_ProcessEventModal(const Event* pe, HWind id);

// Register Event Handlers: task specific and window specific
void Task_SubLoop(unsigned int mask, int time_step, Listener_FOnEvent pEventHandler, void *pHandle);
Msg* Task_PostAndWaitForReply(Msg* pmsg, HTask task);
Msg* Task_WPostAndWaitForReply(Msg* pmsg, HWind w, HIcon i);
void throw_Task_RegisterEventHandler(Listener_FOnEvent pEventHandler, void *pHandle, bool bFirst);
void Task_DeRegisterEventHandler(Listener_FOnEvent pEventHandler, void *pHandle);
void throw_Task_AddListener(int event, Listener_FOnEvent pEventHandler, void *pHandle, bool bFirst);
void Task_RemoveListener(int event, Listener_FOnEvent pEventHandler, void *pHandle);

void throw_Task_AddMsgListener(int msgtype, Listener_FOnEvent pEventHandler, void *pHandle, bool bFirst);
void Task_RemoveMsgListener(int msgtype, Listener_FOnEvent pEventHandler, void *pHandle);

// Task information
HTask Task_GetId(void);
int Task_GetWimpVersion(void);
int Task_GetTerritoryNumber(void);
unsigned int Task_GetPollMask(void);
int Task_GetPollTimeStep(void);
const char* Task_GetName(void);
const char* Task_GetDir(void);
const char* Task_GetSpriteName(void);
CSpriteArea* Task_GetSpriteArea(void);
const Mode_Info* Task_GetModeInfo(void);
const Mouse* Mouse_Get(void);
void Mouse_Set(int x, int y);

void Task_SetModeInfo(void);
void Task_SetPollTimeStep(int step);

// Task message reporting
void Task_ReportException(void);
#ifdef __CC_NORCROFT
#pragma -v1 // hint to the compiler to check f/s/printf format
#endif
void Task_ReportError(const char* pmsg, ...);
void Task_DescribeError(const _kernel_oserror* e, const char* pmsg, ...);
void Task_ReportInfo(const char* pmsg, ...);
bool Task_Query(bool invert, const char* pmsg, ...);
#ifdef __CC_NORCROFT
#pragma -v0 // return to default
#endif
int  Task_ReportVMsg(unsigned int flags, const char* pmsg, va_list arg);
void Task_DescribeVMsg(unsigned int flags, const _kernel_oserror* e, const char* pmsg, va_list arg);
const _kernel_oserror* Task_ReportOSError(const _kernel_oserror* e);
void Task_NoError(const _kernel_oserror* e);
const _kernel_oserror* Task_LastOSError(void);

// Message reply
const _kernel_oserror* Task_SendMsg(Msg* pmsg, HTask task);
const _kernel_oserror* Task_PostMsg(Msg* pmsg, HTask task);
const _kernel_oserror* Task_WSendMsg(Msg* pmsg, HWind w, HIcon i);
const _kernel_oserror* Task_WPostMsg(Msg* pmsg, HWind w, HIcon i);
const _kernel_oserror* Task_AcknowledgeMsg(const Msg* pmsg);
const _kernel_oserror* Task_HelpReply(const Msg_HelpRequest* pmsg, const char* phelp);
bool Task_HelpReply_FromMenu(const Msg_HelpRequest* pmsg, const char* ptkitem, const char* ptksub);

void Task_WimpProcessKey(int code);

JobList* Task_GetJobList(void);

void KeyGrabber_Activate(void);
void KeyGrabber_Deactivate(void);

#ifdef __cplusplus
}
#endif

#endif
