#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "kernel.h"
#include "swis.h"

#define Buggy "<Obey$Dir>.Buggy"
#include "Buggy.h" // my debugging code
#include "Wimpy.h" // some Wimp definitions

// Some global variables so I need not pass them on over and over again
// ... or create them over and over again for subroutine calls
_kernel_swi_regs SWIRegs;
_kernel_oserror *OSError;
const char MyTaskName[] = "BarIcons";
t_TaskHandle MyTaskHandle = 0;
t_IconHandle MyBarIcon = 0;
int  MyPollMask = PollMask_Standard;
t_WimpPollBlock WimpPollBlockStorage;
t_WimpPollBlock *WimpPollBlock;

// Function for SWI Wimp_CloseDown
void WimpCloseDown(char *Notes) {
	// Call Wimp_CloseDown if I have a TaskHandle
	if (MyTaskHandle != 0) {
		SWIRegs.r[0] = TASK;
		SWIRegs.r[1] = MyTaskHandle;
		_kernel_swi(Wimp_CloseDown,&SWIRegs,&SWIRegs);
	}
	// If there was an error say so
	if (OSError != NULL) {
		BuggyError(Notes);
		SWIRegs.r[0] = (int)OSError;
		SWIRegs.r[1] = 1;
		SWIRegs.r[2] = (int)Notes;
		_kernel_swi(Wimp_ReportError,&SWIRegs,&SWIRegs);
	}
	// Exit
	_kernel_swi(OS_Exit,&SWIRegs,&SWIRegs);
	exit(0);
}

// Function for SWI Wimp_Initalise
void WimpInitialise(void) {
	SWIRegs.r[0] = 310;
	SWIRegs.r[1] = TASK;
	SWIRegs.r[2] = (int)&MyTaskName;
	SWIRegs.r[3] = (int)NULL;
	if((OSError = _kernel_swi(Wimp_Initialise,&SWIRegs,&SWIRegs)) != NULL) { WimpCloseDown("Wimp_Initialise"); }
	MyTaskHandle = SWIRegs.r[1];
}

// Function for SWI Wimp_Poll
int WimpPoll(void) {
	SWIRegs.r[0] = MyPollMask;
	SWIRegs.r[1] = (int)&WimpPollBlockStorage;
	if((OSError = _kernel_swi(Wimp_Poll,&SWIRegs,&SWIRegs)) != NULL) { WimpCloseDown("Wimp_Poll"); }
	// I would expect that the block I pass to Wimp_Poll is the one filled but the PRMs do not guarantee that!
	WimpPollBlock = (t_WimpPollBlock *)SWIRegs.r[1];
	return(SWIRegs.r[0]);
}

// Function to put Icon on icon bar with SWI Wimp_CreateIcon
t_IconHandle WimpCreateIconBarIcon(char *Sprite, t_WindowHandle LeftRight) {
	t_WimpCreateIconBlock WimpCreateIconBlock;
	WimpCreateIconBlock.Window = LeftRight;
	WimpCreateIconBlock.Icon.MinX = 0;
	WimpCreateIconBlock.Icon.MinY = 0;
	WimpCreateIconBlock.Icon.MaxX = 69;
	WimpCreateIconBlock.Icon.MaxY = 68;
	WimpCreateIconBlock.Icon.IconFlags = IconBarIconFlags;
	WimpCreateIconBlock.Icon.IconData.IconSpriteIndirect.Sprite = Sprite;
	WimpCreateIconBlock.Icon.IconData.IconSpriteIndirect.Area = WimpSpriteArea;
	WimpCreateIconBlock.Icon.IconData.IconSpriteIndirect.Length = strlen(Sprite);
	SWIRegs.r[0] = 0;
	SWIRegs.r[1] = (int)&WimpCreateIconBlock;
	if((OSError = _kernel_swi(Wimp_CreateIcon,&SWIRegs,&SWIRegs)) != NULL) { WimpCloseDown("Wimp_CreateIcon"); }
	return(SWIRegs.r[0]);
}

// Function to remove Icon  from icon bar with SWI Wimp_DeleteIcon
void WimpDeleteIconBarIcon(t_IconHandle Icon) {
	t_WimpDeleteIconBlock WimpDeleteIconBlock;
	WimpDeleteIconBlock.Window = WindowIconbar;
	WimpDeleteIconBlock.Icon = Icon;
	SWIRegs.r[0] = 0;
	SWIRegs.r[1] = (int)&WimpDeleteIconBlock;
	if((OSError = _kernel_swi(Wimp_DeleteIcon,&SWIRegs,&SWIRegs)) != NULL) { WimpCloseDown("Wimp_DeleteIcon"); }
}

// Function to check if a key is pressed
int OS_KeyPressCheck(int Key) {
	SWIRegs.r[0] = 129;
	SWIRegs.r[1] = Key ^ 0xff;
	SWIRegs.r[2] = 0xff;
	if((OSError = _kernel_swi(OS_Byte,&SWIRegs,&SWIRegs)) != NULL) { WimpCloseDown("OS_Byte 129"); }
	BuggyRegs("Key",2);
	return((SWIRegs.r[1] == 0xff));
}

int main (int argc, char *argv[]) {

	int ReasonCode;
	const char MyIconName1[] = "Switcher";
	const char MyIconName2[] = "!Help";
	char *MyIconName = (char*)&MyIconName1;
	t_WindowHandle MyIconSide = IconBarIconRight;

	BuggyClear;

	WimpInitialise();

	MyBarIcon = WimpCreateIconBarIcon(MyIconName,MyIconSide);

	while (True) {
		ReasonCode = WimpPoll();

		// Handle the request
		switch(ReasonCode) {
		// Mouse click
		case ReasonCode_MouseClick:
			if (WimpPollBlock->MouseClick.Icon == MyBarIcon) {
				switch(WimpPollBlock->MouseClick.Buttons) {
				case MouseButtonRight: // Kill my task - if Shift pressed
					if (OS_KeyPressCheck(KeyShift)) { WimpCloseDown(""); }
					break;
				case MouseButtonMiddle: // Toggle icon image
					WimpDeleteIconBarIcon(MyBarIcon);
					MyIconName = (MyIconName == (char*)&MyIconName1) ? (char*)&MyIconName2 : (char*)&MyIconName1;
					MyBarIcon = WimpCreateIconBarIcon(MyIconName,MyIconSide);
					break;
				case MouseButtonLeft: // Toggle side on icon bar
					WimpDeleteIconBarIcon(MyBarIcon);
					MyIconSide = (MyIconSide == IconBarIconRight) ? IconBarIconLeft : IconBarIconRight;
					MyBarIcon = WimpCreateIconBarIcon(MyIconName,MyIconSide);
					break;
				}
			}
			break;
		// User message
		case ReasonCode_UserMessage:
		case ReasonCode_UserMessageRecorded:
			if (WimpPollBlock->UserMessage.MessageCode == UserMessage_Quit) {
				WimpCloseDown(""); // note that OSError is NULL here
			}
			break;
		}
	}

}

