#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "oslib/os.h"
#include "oslib/osfile.h"
#include "oslib/taskmanager.h"
#include "oslib/wimp.h"
#include "config.h"
#include "display.h"
#include "error.h"
#include "globals.h"
#include "util.h"

void usage(void)
{
    printf(PROGNAME " " VERSION "\n");
    printf("Usage: " PROGNAME " [OPTIONS] FILE\n\n");
    printf("  -n, --name STRING   use STRING as window title\n");
    printf("  -d, --delete        delete FILE when window is closed\n\n");
}

int instance_count(wimp_t handle)
{
    taskmanager_task task;
    char **end = NULL;
    int count = 0, i = 0;
    while ((i = taskmanager_enumerate_tasks (i,
                                             &task,
                                             sizeof (task),
                                             end)) > 0)
    {
        if (!strncmp(task.name, PROGNAME, strlen(PROGNAME)))
            ++count;
        if (task.task == handle)
            break;
    }
    return count;
}

int main(int argc, char *argv[])
{
    os_error *err;
    wimp_event_no event;
    wimp_poll_flags mask = wimp_MASK_LEAVING | wimp_MASK_ENTERING |
                           wimp_MASK_LOSE | wimp_MASK_GAIN |
                           wimp_MASK_POLLWORD;
    wimp_block block;
    wimp_t handle;
    char *tname;
    char *title = NULL;
    char *filename = NULL;
    bool remove = false;
    bool quit = false;
    int i = 0;
    int count = -1;
    wimp_MESSAGE_LIST(2) mlist = { message_MODE_CHANGE, message_QUIT };

    if (argc == 1)
    {
        usage();
        return 0;
    }

    for (i = 1; i < argc; ++i)
    {
        if ((!strcmp(argv[i], "--name") || !strcmp(argv[i], "-n"))
            && argv[i + 1])
        {
            title = argv[i++ + 1];
        }
        else if (!strcmp(argv[i], "--delete") || !strcmp(argv[i], "-d"))
            remove = true;
        else if (!filename)
            filename = argv[i];
        else
        {
            usage();
            return 1;
        }
    }

    if (!filename)
    {
        usage();
        return 1;
    }

    if (!title)
    {
        for (i = strlen(filename) - 1; i >= 0; --i)
            if (filename[i] == '.')
                break;
        if (i)
            title = strdup(filename + i + 1);
        else
            title = "untitled";
    }

    tname = malloc(12 + strlen(title));
    strcpy(tname, PROGNAME " (");
    strcat(tname, title);
    strcat(tname, ")");

    JPEG_FileInit(filename);

    if (err = xwimp_initialise(wimp_VERSION_RO3,
                               tname,
                               (wimp_message_list *) &mlist,
                               NULL,
                               &handle))
    {
        if (err->errnum == 260)
        {
            /* WIMP is already initialised (e.g. inside a TaskWindow),
               therefore start new task */
            const char const* str_null = " { > null: }";
            byte *ram_limit;
            os_date_and_time *start;
            int next_slot;
            char *command = malloc(strlen(os_get_env(&ram_limit, &start))
                                   +strlen(str_null)
                                   +1);
            sprintf(command, "%s%s", os_get_env(&ram_limit, &start), str_null);
            wimp_slot_size(-1, -1, NULL, &next_slot, NULL);
            wimp_slot_size(-1, PROGMEM, NULL, NULL, NULL);
            wimp_start_task(command);
            wimp_slot_size(-1, next_slot, NULL, NULL, NULL);
            free(command);
            exit(0);
        }
        else
        {
            /* real error, propagate it */
            err_fatal(err);
        }
    }

    before_wimp = false;

    do {
        event = wimp_poll(mask, &block, 0);

        switch (event)
        {
            case wimp_NULL_REASON_CODE:
                count = instance_count(handle);
                JPEG_WindowInit(title, count);
                JPEG_Open();
                mask |= wimp_MASK_NULL;
                break;
            case wimp_REDRAW_WINDOW_REQUEST:
                JPEG_Redraw(&block.redraw);
                break;
            case wimp_OPEN_WINDOW_REQUEST:
                JPEG_Reopen(&block.open);
                break;
            case wimp_CLOSE_WINDOW_REQUEST:
                quit = true;
            case wimp_USER_MESSAGE:
            case wimp_USER_MESSAGE_RECORDED:
            case wimp_USER_MESSAGE_ACKNOWLEDGE:
                switch (block.message.action)
                {
                    case message_QUIT:
                        quit = true;
                        break;
                    case message_MODE_CHANGE:
                        if (count == -1)
                        {
                            count = instance_count(handle);
                            JPEG_WindowInit(title, count);
                            mask |= wimp_MASK_NULL;
                        }
                        JPEG_Open();
                        break;
                }
        }
    } while (!quit);

    JPEG_Free();
    free(tname);
    
    if (remove)
        osfile_delete(filename, 0, 0, 0, 0);
    
    wimp_close_down(handle);

    return 0;
}
