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

#include "WimpLib:mem.h"
#include "WimpLib:DragDrop.h"
#include "WimpLib:Exception.h"
#include "WimpLib:File.h"
#include "WimpLib:Hourglass.h"
#include "WimpLib:Task.h"
#include "WimpLib:Utils.h"
#include "WimpLib:Window.h"
#include "WimpLib:CIcon.h"

#define AMPlayer_Instance		0x52E10
#define AMPlayer_Stop			0x52e01
#define DiskSample_Configure	0x52ec1
#define DSym_Load				0x45880
#define DSym_ResetParams		0x45887
#define DSym_SongPos			0x4588C
#define DSym_TuneControl		0x4588D
#define ExpressionMod_Stop		0x8A803
#define MidiPlay_Stop			0x45342
#define PlayIt_Stop				0x4d14b
#define QTM_Stop				0x47e42
#define QTM_Clear				0x47e44
#define TimPlayer_Configure		0x51381
#define Tracker_Stop			0x43204

extern const char ProgramName[];
const char ProgramName[] = "ResetSound";
static const char ProgramSprite[] = "!resetsound";
static const char ProgramDir[] = "<ResetSound$Dir>";

static struct
{
	HWind	Wind;
} App;

static void App_Close(void)
{
	Window_Delete(App.Wind);

	Task_NotTask(EXIT_SUCCESS);
}

static EListenerAction App_DefaultHandler(void* handle, const Event* e)
{
	IGNORE(handle);

	switch(e->Type)
	{
		case EEvent_WindowClose:
		{
			App_Close();
		}
		break;
		case EEvent_Mouse:
		{
			const Mouse* m = e->pData;

			if (m->w == App.Wind)
			{
				switch(m->i)
				{
					case 0:
					{
                    	int handle = -1;
                    	char buffer[128];
                    	do
                    	{
							if (NULL != _swix(AMPlayer_Instance, _INR(0,4)|_OUT(2)
								, 0, 4, handle, (int) buffer, sizeof(buffer)
								, &handle
								)) break;
							if (handle != -1)
							{
								_swix(AMPlayer_Stop, _IN(0)|_IN(8), 0|0x80000000, handle);
								_swix(AMPlayer_Instance, _INR(0,2), 0, 2, handle);
							}
						}
			            while (handle != -1);
					}
					break;
					case 2:
					{
						_swix(DiskSample_Configure, _IN(0), -1);
					}
					break;
					case 4:
					{
						_swix(DSym_TuneControl, 0);
						_swix(DSym_SongPos, _IN(0)|_IN(1), 0, 0);
						_swix(DSym_ResetParams, 0);
						_swix(DSym_Load, _IN(0), -1);
					}
					break;
					case 6:
					{
						_kernel_swi_regs regs;

						regs.r[0] = 0;
						regs.r[1] = 0;
						regs.r[2] = 0;
						regs.r[3] = 0;
						regs.r[4] = 0;
						regs.r[5] = 0;
						regs.r[6] = 0;
						regs.r[7] = 0;
						regs.r[8] = 0;
						// Xmatrix_TRKPause
						_kernel_swi(0x06bd5a, &regs, &regs);

						regs.r[0] = 0;
						regs.r[1] = 0;
						regs.r[2] = 0;
						regs.r[3] = 0;
						regs.r[4] = 0;
						regs.r[5] = 0;
						regs.r[6] = 0;
						regs.r[7] = 0;
						regs.r[8] = 0;
						// matrix_TRKRelease
						_kernel_swi(0x06bd54, &regs, &regs);
					}
					break;
					case 8:
					{
						_swix(MidiPlay_Stop, 0);
					}
					break;
					case 10:
					{
						_swix(PlayIt_Stop, 0);
					}
					break;
					case 12:
					{
						_swix(QTM_Stop, 0);
						_swix(QTM_Clear, 0);
					}
					break;
					case 14:
					{
						_swix(Tracker_Stop, 0);
					}
					break;
					case 16:
					{
						_swix(TimPlayer_Configure, _IN(0), -1);
					}
					break;
					case 18:
					{
						_swix(ExpressionMod_Stop, 0);
					}
					break;
				}
				return EListenerAction_StopEvent;
			}
		}
		break;
		case EEvent_Message:
		case EEvent_MessageWantAck:
		{
			const Msg_FileData* msg = e->pData;

			switch(msg->hdr.action)
			{
				case EMsg_Quit:
				{
					App_Close();
				}
				break;
			}
		}
		break;
	}

	return EListenerAction_ContinueEvent;
}

static int messages[] =
{
	EMsg_DataSave,
	EMsg_DataSaveAck,
	EMsg_DataLoad,
	EMsg_DataLoadAck,
	EMsg_Dragging,
	EMsg_DragClaim,
	EMsg_HelpRequest,
	EMsg_MenusDeleted,
	0
};

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

	/* Wimp initialisations */
	throw_Task_Task(false, 310, ProgramName, ProgramSprite, ProgramDir, messages);

	try
	{
		throw_Task_RegisterEventHandler(App_DefaultHandler, NULL, false);

		App.Wind = throw_Window_CreateFrom("Main", NULL);

		throw_Window_RegisterEventHandler(App.Wind, App_DefaultHandler, NULL, false);
		Window_Open(App.Wind);

		Task_MainLoop(EPollMask_WindowPtrLeave | EPollMask_WindowPtrEnter, 0);
	}
	catch
	{
		Task_ReportException();
		Task_NotTask(EXIT_FAILURE);
	}
	catch_end

	return 0;
}
