#include "WimpLib:DCS.h"

#include <string.h>

#include "WimpLib:Exception.h"
#include "WimpLib:Message.h"
#include "WimpLib:Task.h"
#include "WimpLib:Template.h"
#include "WimpLib:Window.h"

#define Icon_Text   0
#define Icon_Ok     1
#define Icon_Cancel 2

DCS_Enum DCS_Ask(const char* text)
{
	return (DCS_Enum) Box_Ask(text, Msg_Lookup("ButDCS"));
}

int Box_Ask(const char* text, const char* buttons)
{
	Event*           e;
	unsigned int     mask = Task_GetPollMask();
	const Mode_Info* Screen = Task_GetModeInfo();
	int              bOpen = true;
	int              ret = Icon_Cancel;
	HWind volatile   id = HWind_None;
	CWindState       o;
	int              width, height;
	CTemplate* volatile t = NULL;
	CWind* pw;
	CIcon* pi;
	char*  p1;
	char*  p2;
	int    count = 1;
	int    len = 10;
	int    i;

	try
	{
		t = throw_Templates_Copy("MsgBox");
		pw = Template_GetWindow(t);

		p1 = (char*) buttons;
		while ((p2 = strchr(p1, ',')) != NULL)
		{
			if (len < p2 - p1) len = p2 - p1;
			p1 = p2 + 1;
			count++;
		}
		if (len < strlen(p1)) len = strlen(p1);
		len = len * 16 + 20;

		// Set size of default action button
		pi = (CIcon*) (pw + 1);
		pi++;
		pi->box.x1 = pi->box.x0 + len + 16;
		pi++;

		// Set size of other action buttons
		for (i = 2; i < pw->nicons; i++, pi++)
		{
			pi->box.x1 = pi->box.x0 + len;
		}

		// Set size of window
		pi--;
		pw->ex.x1 = pi->box.x1 + 32;
		pw->o.o.cvt.box.x1 = pw->o.o.cvt.box.x0 + pw->ex.x1 - pw->ex.x0;

		// Create dialog box
		id = throw_Window_Create(t, NULL);

		// Delete unrequired icons
		for (i = count + 1; i < pw->nicons; i++)
		{
			Icon_Delete(id, i);
		}

		Icon_SetData(id, Icon_Text, text);

		p1 = (char*) buttons;
		for (i = 1; i <= count; i++)
		{
			p2 = strchr(p1, ',');
			if (p2)
			{
				*p2 = '\0';
				Icon_SetData(id, i, p1);
				*p2 = ',';
				p1 = p2 + 1;
			}
			else
				Icon_SetData(id, i, p1);
		}

		// Center it on screen and open it
		o = Window_GetState(id);
		width = o.o.cvt.box.x1 - o.o.cvt.box.x0;
		height = o.o.cvt.box.y1 - o.o.cvt.box.y0;
		o.o.cvt.box.x0 = (Screen->box.x1 - width) / 2;
		o.o.cvt.box.x1 = o.o.cvt.box.x0 + width;
		o.o.cvt.box.y0 = (Screen->box.y1 - height) / 2;
		o.o.cvt.box.y1 = o.o.cvt.box.y0 + height;
		Window_WimpOpen(&o.o);
		o = Window_GetState(id);

		// Set an invisible caret, so that we can grab key presses
		Caret_SetInvisible(id);

		while (bOpen)
		{
			// protect against unexpected situation
			if (!Window_IsOpen(id))
			{
				bOpen = false;
				ret = Icon_Cancel;
			}

			// allow key presses
			e = Task_PollIdle(mask & ~EPollMask_Key, Task_GetPollTimeStep());

			switch (e->Type)
			{
				case EEvent_Key:
				{
					const Event_Key* key = e->pData;

					// Test ESC key
					if (key->code == 27)
					{
						bOpen = false;
						ret = Icon_Cancel;
					}
					// Test RETURN key
					if (key->code == 13)
					{
						bOpen = false;
						ret = Icon_Ok;
					}
					// Other keys are not processed
					Task_WimpProcessKey(key->code);
					continue;
				}
				break;
				case EEvent_Mouse:
				{
					const Mouse* m = e->pData;

					if (m->w == id)
					{
						ret = m->i;
						bOpen = false;
						continue;
					}
				}
				break;
			}

			// Normal processing
			Task_ProcessEventModal(e, id);
		}

		// Close and destroy Window
		Window_Close(id);
		Window_Delete(id);
	}
	catch
	{
		Window_Delete(id);
		Templates_Remove(t);
		Task_ReportException();
		return Icon_Cancel;
	}
	catch_end

	return ret;
}
