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

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

#include "wimpreadsysinfo.h"
#include "toolbox.h"
#include "window.h"

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

#define WIDTH 80
#define HEIGHT 100

static char d[HEIGHT][WIDTH+1];

static char *display[HEIGHT];

static int lastbracketwidth;

static int x;
static int maxx;
static bool needblank;

static int extent = 10;
static int scrolled = 1;

last_proc_report contest_type;

static void display_redraw(wimp_draw *redraw, bool more, bool blank);

void display_init()
{
    int i;

    for (i=0; i<HEIGHT; i++)
    {
        display[i] = d[i];
    }
}

void display_scroll()
{
    int i;
    char *temp = display[0];
    wimp_w w = window_get_wimp_handle(0, displayhandle);
    wimp_draw update;
    bool more;

    /* increase extent */
    if (scrolled < HEIGHT)
    {
        scrolled++;
        if (scrolled > extent)
        {
            os_box b;
            extent++;

            b.x0=0;
            b.x1=WIDTH*16;
            b.y0=-HEIGHT*32;
            b.y1=-(HEIGHT-scrolled)*32;
            window_set_extent(0, displayhandle, &b);
        }
    }

    /* parse the line just printed to find out what we're doing... */
    if (display[HEIGHT-1][0] == '[')
    {
        xwimptextop_string_width(display[HEIGHT-1], 22, &lastbracketwidth);

        if (strncmp(display[HEIGHT-1] + 20, "] Loaded ", 9) == 0)
        {
            if (strncmp(display[HEIGHT-1] + 29, "RC5", 3) == 0)
            {
                contest_type = RC5_being_processed;
                show_iconbar();
            }
            else if (strncmp(display[HEIGHT-1] + 29, "DES", 3) == 0)
            {
                contest_type = DES_being_processed;
                show_iconbar();
            }
        }
        else if (strcmp(display[HEIGHT-1] + 22, "Shutdown message received - Block being saved.") == 0)
        {
            contest_type = nothing_being_processed;
            show_iconbar();
        }
        else if (strncmp(display[HEIGHT-1] + 20, "] Completed ", 12) == 0)
            moo(playsound());
    }

    update.w = w;
    update.box.x0 = 0;
    update.box.x1 = WIDTH*16,
    update.box.y0 = -HEIGHT*32;
    update.box.y1 = -(HEIGHT-1)*32;

    /* Ensure bottom line is up to date before we scroll it */
    more = wimp_update_window(&update);
    display_redraw(&update, more, needblank);

    for (i=0; i<HEIGHT-1; i++)
    {
        display[i] = display[i+1];
    }

    memset(temp, 0, WIDTH);
    display[HEIGHT-1]=temp;

    /* Scroll up */
    wimp_block_copy(w,
                    0, -HEIGHT*32, WIDTH*16, -32,
                    0, -(HEIGHT-1)*32);

    /* blank bottom line */
    update.box.x0 = 0;
    update.box.x1 = WIDTH*16,
    update.box.y0 = -HEIGHT*32;
    update.box.y1 = -(HEIGHT-1)*32;
    more = wimp_update_window(&update);
    display_redraw(&update, more, TRUE);
}

bool display_writec(char c)
{
    bool scrolled = FALSE;

    if (c==13)
    {
        x=0;
        return FALSE;
    }

    if (c < 32 && c != 10)
        return FALSE;

    if (x < maxx) needblank = TRUE;

    if (c!=10)
        display[HEIGHT-1][x++] = c;

    if (x > maxx) maxx = x;

    if (x == WIDTH || c == 10)
    {
        x = maxx = 0;
        display_scroll();
        needblank = FALSE;
        scrolled = TRUE;
    }

    return scrolled;
}

bool display_puts(const char *s)
{
    bool scrolled=FALSE;

    while (*s)
    {
        if (display_writec(*s))
            scrolled = TRUE;
        s++;
    }

    return scrolled;
}

int taskwindow_output_handler(wimp_message *message, void *handle)
{
    taskwindow_message_data *data = (taskwindow_message_data *) &message->data;
    int i, ox=x;
    wimp_draw update;
    bool scrolled=FALSE;

    for (i=0; i<data->size; i++)
    {
        if (display_writec(data->data[i]))
            scrolled=TRUE;
    }

    if (scrolled && x==0 || x==ox && !needblank)
        return 1;

    update.w = window_get_wimp_handle(0, displayhandle);
    #if 0
    update.box.x0 = scrolled ? 0 : ox*16;
    update.box.x1 = x*16;
    #else
    update.box.x0 = 0;
    update.box.x1 = WIDTH*16;
    #endif
    update.box.y0 = -HEIGHT*32;
    update.box.y1 = -(HEIGHT-1)*32;

    display_redraw(&update, wimp_update_window(&update), needblank);

    needblank = FALSE;

    return 1;
}

static void display_redraw(wimp_draw *redraw, bool more, bool blank)
{
    font_f font;

    if (xwimpreadsysinfo_font(&font, NULL))
       font = font_SYSTEM;

    while (more)
    {
        int top, bottom, i;

        if (blank)
            os_clg();

        if (font != font_SYSTEM)
            wimptextop_set_colour(os_COLOUR_BLACK, os_COLOUR_WHITE);

        top = (-redraw->clip.y1 + (redraw->box.y1-redraw->yscroll))/32 - 1;
        bottom  = (-redraw->clip.y0 + (redraw->box.y1-redraw->yscroll) + 31)/32 + 1;

        if (top < 0) top = 0;
        if (bottom > HEIGHT) bottom = HEIGHT;

        for (i=top; i<bottom; i++)
        {
            if (font == font_SYSTEM)
            {
            	os_plot(os_MOVE_TO,
                        redraw->box.x0 - redraw->xscroll,
                    	redraw->box.y1 - redraw->yscroll - i*32 - 4);
            	os_write0(display[i]);
            }
            else
            {
                int indent, skip;

                // line-up hackery...
                if (strncmp(display[i], "                      ", 22) == 0)
                {
                    indent = lastbracketwidth;
                    skip = 22;
                }
                else
                {
                    indent = 0;
                    skip = 0;
                }
                wimptextop_paint(wimptextop_GIVEN_BASELINE, display[i] + skip,
                                 redraw->box.x0 - redraw->xscroll + 4 + indent,
                                 redraw->box.y1 - redraw->yscroll - i*32 - 28);
            }
        }
        more = wimp_get_rectangle(redraw);
    }
}

int display_redraw_handler(wimp_event_no event_code, wimp_block *event,
                           toolbox_block *id, void *handle)
{
    bool more;

    more = wimp_redraw_window(&event->redraw);

    display_redraw(&event->redraw, more, FALSE);

    return 1;
}

void display_set_title(const char *title)
{
    window_set_title(0, displayhandle, title);

    fade_client_menu();

    show_iconbar();
}
