#include <stdlib.h>
#include <string.h>
#include "oslib/os.h"
#include "oslib/osfile.h"
#include "oslib/osmodule.h"
#include "oslib/fileswitch.h"
#include "oslib/wimp.h"
#include "oslib/jpeg.h"
#include "config.h"
#include "error.h"
#include "globals.h"
#include "util.h"

static jpeg_image *image = NULL;
static int size = 0;
static int width = 0;
static int height = 0;
static char *title = NULL;

static wimp_window mainwin;
static wimp_w mainhandle;

static int xeig;
static int yeig;

void JPEG_SetScale(void)
{
    os_read_mode_variable(os_CURRENT_MODE, os_MODEVAR_XEIG_FACTOR, &xeig);
    os_read_mode_variable(os_CURRENT_MODE, os_MODEVAR_YEIG_FACTOR, &yeig);
}

void JPEG_FileInit(char *filename)
{
    os_error *e;
    fileswitch_object_type type;
    jpeg_info_flags info_flags;
    
    if (e = xjpegfileinfo_dimensions(filename, &info_flags,
                                     &width, &height, 0, 0, 0))
    {
        err_fatal(e);
    }

    type = osfile_read_stamped_no_path(filename, 0, 0, &size, 0, 0);
    
    if (type == osfile_IS_FILE)
    {
        image = osmodule_alloc(size);
        
        if (!image)
        {
            err_fatal(&EMALLOC);
        }
        
        (void) osfile_load_stamped_no_path(filename, (byte*) image, 0, 0, 0, 0);
    }
}

void JPEG_WindowInit(char *name, int count)
{
    int xscr, yscr, xpos, ypos, xoffset, yoffset, xstep, ystep;

    title = strdup(name);
    
    JPEG_SetScale();

    os_read_mode_variable(os_CURRENT_MODE, os_MODEVAR_XWIND_LIMIT, &xscr);
    os_read_mode_variable(os_CURRENT_MODE, os_MODEVAR_YWIND_LIMIT, &yscr);
    
    xstep = xscr * (1 << xeig) / 20;
    ystep = yscr * (1 << yeig) / 16;
    xoffset = xstep << 1;
    yoffset = ystep << 1;
    xscr *= (1 << xeig);
    yscr *= (1 << yeig);

    xpos = xoffset +
           (count * xstep) %
           (xscr - (1 << xeig) * width - (xoffset << 1));
    ypos = yscr - yoffset - (1 << yeig) * height -
           (count * ystep) %
           (yscr - (1 << yeig) * height - (yoffset << 1));
    
    mainwin.visible.x0   = xpos;
    mainwin.visible.x1   = mainwin.visible.x0 + (1 << xeig) * width;
    mainwin.visible.y0   = ypos;
    mainwin.visible.y1   = mainwin.visible.y0 + (1 << yeig) * height;
    mainwin.xscroll      = 0;
    mainwin.yscroll      = 0;
    mainwin.next         = (wimp_w) -1;
    mainwin.flags        = wimp_WINDOW_MOVEABLE |
                           wimp_WINDOW_NO_BOUNDS |
                           wimp_WINDOW_CLOSE_ICON |
                           wimp_WINDOW_TITLE_ICON |
                           wimp_WINDOW_NEW_FORMAT;
    mainwin.title_fg     = wimp_COLOUR_BLACK;
    mainwin.title_bg     = wimp_COLOUR_LIGHT_GREY;
    mainwin.work_fg      = wimp_COLOUR_BLACK;
    mainwin.work_bg      = wimp_COLOUR_TRANSPARENT;
    mainwin.scroll_outer = wimp_COLOUR_MID_LIGHT_GREY;
    mainwin.scroll_inner = wimp_COLOUR_VERY_LIGHT_GREY;
    mainwin.highlight_bg = wimp_COLOUR_CREAM;
    mainwin.extra_flags  = 0;
    mainwin.extent.x0    = mainwin.visible.x0;
    mainwin.extent.x1    = mainwin.visible.x1;
    mainwin.extent.y0    = mainwin.visible.y0;
    mainwin.extent.y1    = mainwin.visible.y1;
    mainwin.title_flags  = wimp_ICON_RJUSTIFIED |
                           wimp_ICON_TEXT;
    mainwin.work_flags   = wimp_BUTTON_NEVER;
    mainwin.sprite_area  = (osspriteop_area *) 1;
    mainwin.xmin         = 1;
    mainwin.ymin         = 1;
    memcpy(mainwin.title_data.text, title,
           (strlen(title)>12) ? 12 : strlen(title));
    mainwin.icon_count   = 0;
 
    mainhandle = wimp_create_window(&mainwin);
}

void JPEG_Reopen(wimp_open *wopen)
{
    wopen->visible.x1 = wopen->visible.x0 + (1 << xeig) * width;
    wopen->visible.y1 = wopen->visible.y0 + (1 << yeig) * height;
    wimp_open_window(wopen);
}

void JPEG_Open(void)
{
    os_box extent;
    wimp_window_state state;
    JPEG_SetScale();
    extent.x0 = 0;
    extent.y0 = 0;
    extent.x1 = (1 << xeig) * width;
    extent.y1 = (1 << yeig) * height;
    wimp_set_extent(mainhandle, &extent);
    state.w = mainhandle;
    wimp_get_window_state(&state);
    JPEG_Reopen((wimp_open *) &state);
}

void JPEG_Redraw(wimp_draw *redraw)
{
    osbool more;
    
    more = wimp_redraw_window(redraw);
    while (more)
    {
        if (image && size)
        {
            jpeg_plot_scaled(image,
                             redraw->box.x0,
                             redraw->box.y0,
                             0,
                             size,
                             jpeg_SCALE_DITHERED | jpeg_SCALE_ERROR_DIFFUSED); 
        }

        more = wimp_get_rectangle(redraw);
    }

}

void JPEG_Free(void)
{
    wimp_close_window(mainhandle);    
    if (image)
    {
        osmodule_free(image);
    }
    image = NULL;
    size = 0;
    width = 0;
    height = 0;
    title = NULL;
}
