#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include "wimp.h"
#include "taskwindow.h"
#include "toolbox.h"

#include "rc5wimp.h"
#include "task.h"
#include "display.h"
#include "config.h"

wimp_t client_taskhandle;
client_mode mode;
static bool restart;
bool paused;

bool client_running()
{
    return client_taskhandle != 0;
}

void client_start(client_mode reqmode)
{
    if (!client_taskhandle)
    {
        char buffer[1024];
        static const char *modestr[] = { "", "", "", "-benchmark", "-test",
                                         "-fetch", "-flush", "-update",
                                         "-forcefetch", "-forceflush" };

        sprintf(buffer,"TaskWindow \"/%s.rc5des %s -guiriscos%s\" -wimpslot 328K "
                       "-name \"RC5DES client\" -ctrl -quit -task &%X -txt &1",
                       our_dir, modestr[reqmode],
                       restart ? " -guirestart" : "",
                       (unsigned int) taskhandle);

        wimp_start_task(buffer);

        restart = TRUE;

        mode = reqmode;
    }
}

static void client_putc(char c)
{
    if (client_taskhandle)
    {
        wimp_message m;
        taskwindow_message_data *const data = (taskwindow_message_data *) &m.data;

        m.size=28;
        m.your_ref=0;
        m.action=message_TASK_WINDOW_INPUT;
        data->size=1;
        data->data[0]=c;

        wimp_send_message(wimp_USER_MESSAGE, &m, client_taskhandle);
    }
}

static const char *modetoken[] = { "WTstopped", "", "WTrunning", "WTbench", "WTtest",
                                   "WTfetch", "WTflush", "WTupdate",
                                   "WTffetch", "WTfflush" };

void client_break(bool hard)
{
    if (client_taskhandle)
    {
        client_unpause();

        client_putc(27);

    	display_set_title(msgs_lookup("WTstopping"));
    }
}

/*void client_update()
{
    client_putc('u');
}*/

void client_kill()
{
    if (client_taskhandle)
    {
        wimp_message m;

        client_unpause();

        m.size=20;
        m.your_ref=0;
        m.action=message_TASK_WINDOW_MORITE;
        wimp_send_message(wimp_USER_MESSAGE, &m, client_taskhandle);
        client_taskhandle=0;
    }
}

void client_pause(void)
{
    if (!paused && client_taskhandle)
    {
        wimp_message m;

        m.size=20;
        m.your_ref=0;
        m.action=message_TASK_WINDOW_SUSPEND;

        wimp_send_message(wimp_USER_MESSAGE, &m, client_taskhandle);

        paused = TRUE;

        display_set_title(msgs_lookup("WTpaused"));
    }
}

void client_unpause(void)
{
    if (paused && client_taskhandle)
    {
        wimp_message m;

        m.size=20;
        m.your_ref=0;
        m.action=message_TASK_WINDOW_RESUME;

        wimp_send_message(wimp_USER_MESSAGE, &m, client_taskhandle);

        paused = FALSE;

        display_set_title(msgs_lookup(modetoken[mode]));
    }
}

int taskwindow_ego_handler(wimp_message *message, void *handle)
{
    NOT_USED(message); NOT_USED(handle);

    client_taskhandle = message->sender;

    display_set_title(msgs_lookup(modetoken[mode]));

    return 1;
}

int taskwindow_morio_handler(wimp_message *message, void *handle)
{
    client_mode m = stopping_for, old_mode = mode;

    NOT_USED(message); NOT_USED(handle);

    client_taskhandle = 0;

    mode = Stop;
    display_set_title(msgs_lookup("WTstopped"));

    stopping_for = Stop;
    contest_type = nothing_being_processed;

    switch (m)
    {
      default:
        break;

      case Shutdown:
      {
        wimp_block b;
        wimp_get_caret_position((wimp_caret *) &b.key);
        b.key.c = wimp_KEY_CONTROL | wimp_KEY_SHIFT | wimp_KEY_F12;
        wimp_send_message(wimp_KEY_PRESSED, (wimp_message *) &b.key, quitsender);
        break;
      }

      case Quit:
        exit(EXIT_SUCCESS);
        break;

      case Test:
      case Benchmark:
      case Fetch:
      case Flush:
      case Update:
      case ForceFetch:
      case ForceFlush:
        /* make it switch back to previous mode when finished :) */
        stopping_for = old_mode;
        client_start(m);
        break;

      case Configure:
        stopping_for = old_mode;
        configure();
        break;

      case Run:
        client_start(Run);
        break;
    }

    return 1;
}

