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

#include "osfscontrol.h"
#include "osfile.h"
#include "wimp.h"
#include "taskwindow.h"

#include "toolbox.h"
#include "window.h"
#include "hourglass.h"

#include "event.h"
#include "config.h"
#include "graph.h"
#include "rc5wimp.h"
#include "rc5graph.h"

extern int strcasecmp(const char *, const char *);

typedef struct graph_window
{
    struct graph_window *next;
    toolbox_o o;
    wimp_w w;
    graph_window_data *data;
}
graph_window;

static graph_window *graph_list;

static int graph_open_handler(wimp_event_no event_code, wimp_block *event,
                           toolbox_block *id, void *handle)
{
    wimp_window_state state;
    state.w = event->open.w;
    wimp_get_window_state(&state);

    event->open.xscroll = event->open.yscroll = 0;
    wimp_open_window(&event->open);

    if (event->open.visible.x1 - event->open.visible.x0 !=
            state.visible.x1 - state.visible.x0 ||
        event->open.visible.y1 - event->open.visible.y0 !=
            state.visible.y1 - state.visible.y0)
    {
        /*os_box ext;

        ext.x0 = 0;
        ext.x1 = 0x100000;
        ext.y0 = event->open.visible.y0 - event->open.visible.y1;
        ext.y1 = 0;
        wimp_set_extent(event->open.w, &ext);*/

        wimp_force_redraw(event->open.w, -0x1000000,
                                         -0x1000000,
                                         0x1000000,
                                         0x1000000);
    }

    return 1;
}

static int graph_redraw_handler(wimp_event_no event_code, wimp_block *event,
                           toolbox_block *id, void *handle)
{
    bool more;
    graph_window *graph = (graph_window *) handle;

    more = wimp_redraw_window(&event->redraw);

    if (graph->data)
    {
        while (more)
        {
            render_window(graph->data, &event->redraw.box);
            more = wimp_get_rectangle(&event->redraw);
        }
    }
    else
    {
        wimp_icon ic;
        ic.extent.x0 = 0;
        ic.extent.x1 = event->redraw.box.x1 - event->redraw.box.x0;
        ic.extent.y0 = event->redraw.box.y0 - event->redraw.box.y1;
        ic.extent.y1 = 0;
        ic.flags = wimp_ICON_TEXT |
                   wimp_ICON_HCENTRED |
                   wimp_ICON_VCENTRED |
                   wimp_ICON_INDIRECTED |
                   wimp_ICON_FILLED |
                   (wimp_COLOUR_BLACK << wimp_ICON_FG_COLOUR_SHIFT) |
                   (wimp_COLOUR_VERY_LIGHT_GREY << wimp_ICON_BG_COLOUR_SHIFT);
        ic.data.indirected_text.text = msgs_lookup("NoGraph");
        ic.data.indirected_text.validation = "L";
        ic.data.indirected_text.size = 256;

        while (more)
        {
            wimp_plot_icon(&ic);
            more = wimp_get_rectangle(&event->redraw);
        }
    }

    return 1;
}

static int graph_save_handler(wimp_message *message, void *handle)
{
    graph_window *graph = (graph_window *) handle;

    if (message->data.data_xfer.w != graph->w ||
        message->data.data_xfer.file_type != osfile_TYPE_TEXT)
    	return 0;

    message->size = 60;
    message->action = message_DATA_SAVE_ACK;
    message->your_ref = message->my_ref;
    message->data.data_xfer.est_size = -1;
    strcpy(message->data.data_xfer.file_name, "<Wimp$Scrap>");

    wimp_send_message(wimp_USER_MESSAGE, message, message->sender);

    return 1;
}

static int graph_load_handler(wimp_message *message, void *handle)
{
    graph_window *graph = (graph_window *) handle;
    graph_window_data *newgraph;
    int fail;

    if (message->data.data_xfer.w != graph->w ||
        message->data.data_xfer.file_type != osfile_TYPE_TEXT)
    	return 0;

    newgraph = new_graph();
    if (newgraph)
    {
        xhourglass_on();
        fail = read_log_data(newgraph, message->data.data_xfer.file_name);
        xhourglass_off();

        if (fail)
            newgraph = NULL;
    }

    delete_graph(graph->data);
    graph->data = newgraph;

    wimp_force_redraw(graph->w, -0x1000000,
                                -0x1000000,
                                 0x1000000,
                                 0x1000000);

    message->action = message_DATA_LOAD_ACK;
    message->your_ref = message->my_ref;

    if (strcasecmp(message->data.data_xfer.file_name, "<Wimp$Scrap>") == 0)
        remove("<Wimp$Scrap>");

    wimp_send_message(wimp_USER_MESSAGE, message, message->sender);

    return 1;
}

static int graph_close_handler(bits event_code, toolbox_action *event,
                            toolbox_block *id, void *handle)
{
    toolbox_o o = id->this_obj;
    graph_window *graph = (graph_window *) handle;

    if (graph_list == graph)
    {
        graph_list = graph->next;
    }
    else
    {
        graph_window *g;

        for (g = graph_list; g; g = g->next)
        {
            if (g->next == graph)
            {
            	g->next = graph->next;
            	break;
            }
        }
    }

    delete_graph(graph->data);
    free(graph);

    event_deregister_wimp_handler(o, wimp_REDRAW_WINDOW_REQUEST, graph_redraw_handler, handle);
    event_deregister_wimp_handler(o, wimp_OPEN_WINDOW_REQUEST, graph_open_handler, handle);
    event_deregister_toolbox_handler(o, action_WINDOW_DIALOGUE_COMPLETED, graph_close_handler, handle);
    event_deregister_message_handler(message_DATA_LOAD, graph_load_handler, handle);

    toolbox_delete_object(0, o);

    return 1;
}

toolbox_o new_graph_window()
{
    graph_window *graph;
    char buffer[1024];
    os_error err;
    const char *leaf = logname();
    bool fail;

    if (!leaf[0] || strcasecmp(leaf, "none") == 0)
    {
        err.errnum=1;
        strcpy(err.errmess, msgs_lookup("LogReq"));
        report_error(&err);
        return toolbox_NULL_OBJECT;
    }

    graph = malloc(sizeof(graph_window));
    if (!graph)
    	return toolbox_NULL_OBJECT;

    graph->data = NULL;

    canonicalise(leaf, buffer, sizeof buffer);

    graph->data = new_graph();
    if (graph->data)
    {
        xhourglass_on();
        fail = read_log_data(graph->data, buffer);
        xhourglass_off();
        if (fail)
        {
            delete_graph(graph->data);
            graph->data = NULL;
        }
    }

    graph->o = toolbox_create_object(0, (toolbox_id)"Graph");
    graph->w = window_get_wimp_handle(0, graph->o);

    event_register_wimp_handler(graph->o, wimp_REDRAW_WINDOW_REQUEST, graph_redraw_handler, graph);
    event_register_wimp_handler(graph->o, wimp_OPEN_WINDOW_REQUEST, graph_open_handler, graph);
    event_register_toolbox_handler(graph->o, action_WINDOW_DIALOGUE_COMPLETED, graph_close_handler, graph);
    event_register_message_handler(message_DATA_LOAD, graph_load_handler, graph);
    event_register_message_handler(message_DATA_SAVE, graph_save_handler, graph);

    graph->next = graph_list;
    graph_list = graph;

    return graph->o;
}
