#ifdef _plan9_
#include <u.h>
#include <libc.h>
#else
#include <stdlib.h>
#include <string.h>
#endif
#include <filter.h>
#include <fractal.h>
#include <timers.h>
#include <ui_helper.h>
#include <xerror.h>
#include <misc-f.h>
#include "grlib.h"
#define EXPIRETIME 4000000
static void
getpos (uih_context * c, int *x, int *y, int *w, int *h, void *data)
{
    long n = (long) data;
    if (c->messg.message[n] != NULL) {
        int he = xtextheight (c->image, c->font);
        *y = c->messg.messagestart + he * n;
        *h = he;
        *w = xtextwidth (c->image, c->font, c->messg.message[n]);
        *x = (c->image->width - *w) / 2;
    } else {
        *w = *h = *x = *y = 0;
    }
}

static void
draw (uih_context * c, void *data)
{
    int x, y, w;
    long n = (long) data;
    if (c->messg.message[n] != NULL) {
        int h = xtextheight (c->image, c->font);
        y = c->messg.messagestart + h * n;
        w = xtextwidth (c->image, c->font, c->messg.message[n]);
        x = (c->image->width - w) / 2;
        if (c->messg.messagetype[n])
            xprint (c->image, c->font, x, y, c->messg.message[n], (c->image->flags & AAIMAGE) ? BGCOLOR (c) : SELCOLOR (c), BGCOLOR (c), 0);
        else
            xprint (c->image, c->font, x, y, c->messg.message[n], (c->image->flags & AAIMAGE) ? BGCOLOR (c) : FGCOLOR (c), BGCOLOR (c), 0);
    }
}

void
uih_rmmessage (uih_context * c, int pid)
{
    int i;
    for (i = 0; i < NMESSAGES && c->messg.pid[i] != pid; i++);
    if (i == NMESSAGES)
        return;
    if (c->messg.message[i] == NULL)
        return;
    free (c->messg.message[i]);
    tl_remove_timer (c->messg.messagetimer[i]);
    tl_free_timer (c->messg.messagetimer[i]);
    c->messg.message[i] = NULL;
    for (; i < NMESSAGES - 1; i++) {
        c->messg.message[i] = c->messg.message[i + 1];
        c->messg.messagetimer[i] = c->messg.messagetimer[i + 1];
        c->messg.messagetype[i] = c->messg.messagetype[i + 1];
        c->messg.pid[i] = c->messg.pid[i + 1];
    }
    c->messg.message[NMESSAGES - 1] = NULL;
    c->display = 1;
}

void
uih_scrollup (uih_context * c)
{
    uih_rmmessage (c, c->messg.pid[0]);
}

void
uih_clearmessages (uih_context * c)
{
    while (c->messg.message[0] != NULL)
        uih_scrollup (c);
}

void
uih_initmessages (uih_context * c)
{
    long i;
    for (i = 0; i < NMESSAGES; i++) {
        c->messg.message[i] = NULL;
        c->messg.w[i] = uih_registerw (c, getpos, draw, (void *) i, 0);
    }
    c->messg.messagestart = 0;
}

void
uih_destroymessages (uih_context * c)
{
    int i;
    uih_clearmessages (c);
    for (i = 0; i < NMESSAGES; i++)
        uih_removew (c, c->messg.w[i]);
}

static int
uih_message1 (uih_context * c, const char *message, int type)
{
    static int pid;
    int i;
    for (i = 0; i < NMESSAGES && c->messg.message[i] != NULL; i++);
    if (i == NMESSAGES)
        uih_scrollup (c), i--;
    c->messg.message[i] = mystrdup (message);
    c->messg.messagetype[i] = type;
    c->messg.messagetimer[i] = tl_create_timer ();
    tl_reset_timer (c->messg.messagetimer[i]);
    tl_set_interval (c->messg.messagetimer[i], 1);;
    tl_slowdown_timer (c->messg.messagetimer[i], EXPIRETIME);;
    tl_set_handler (c->messg.messagetimer[i], (void (*)(void *)) uih_scrollup, c);
    tl_add_timer (syncgroup, c->messg.messagetimer[i]);
    /*tl_remove_timer (c->messg.messagetimer[i]); */
    c->messg.pid[i] = ++pid;
    c->display = 1;
    return (pid);
}

int
uih_message (uih_context * c, const char *message)
{
    if (c->inhibittextoutput)
        return 0;

    return (uih_message1 (c, message, 0));
}

int
uih_error (uih_context * c, const char *error)
{
    char str[256];
    sprintf (str, "Error: %s", error);
    c->errstring = error;
    return (uih_message1 (c, str, 1));
}

void
uih_printmessages (uih_context * c)
{
    int i;
    for (i = 0; i < NMESSAGES && c->messg.message[i] != NULL; i++)
        x_message (c->messg.message[i], stderr);
}
