#include "config.h"
#include <cstdlib>
#include <cstdio>  /*for NULL */
#include <cstring> /*for memcpy */
#include "filter.h"
struct intdata {
    unsigned char *lastent;
    int changed;
    int first;
};
static int requirement(struct filter *f, struct requirements *r)
{
    r->nimages = 1;
    r->flags |= IMAGEDATA;
    return (f->next->action->requirement(f->next, r));
}

static int initialize(struct filter *f, struct initdata *i)
{
    int x;
    struct intdata *d = (struct intdata *)f->data;
    pixel_t **lines1 =
                (pixel_t **)malloc(sizeof(*lines1) * i->image->height / 2),
            **lines2 =
                (pixel_t **)malloc(sizeof(*lines2) * i->image->height / 2);
    if (lines1 == NULL)
        return 0;
    inhermisc(f, i);
    d->first = 1;
    if (lines2 == NULL) {
        free(lines1);
        return 0;
    }
    if (f->childimage != NULL)
        destroy_image(f->childimage);
    f->image = i->image;
    f->image->flags |= PROTECTBUFFERS;
    i->flags |= DATALOST;
    for (x = 0; x < (i->image->height) / 2; x++) {
        lines1[x] = i->image->currlines[x * 2];
        lines2[x] = i->image->currlines[x * 2 + 1];
    }
    f->childimage = i->image = create_image_lines(
        i->image->width, (i->image->height) / 2, 2, lines1, lines2,
        i->image->palette, NULL, FREELINES | PROTECTBUFFERS,
        f->image->pixelwidth, f->image->pixelheight * 2);
    if (i->image == NULL) {
        free(lines1);
        free(lines2);
        return 0;
    }
    return (f->previous->action->initialize(f->previous, i));
}

static struct filter *getinstance(const struct filteraction *a)
{
    struct filter *f = createfilter(a);
    struct intdata *i = (struct intdata *)calloc(1, sizeof(*i));
    f->data = i;
    f->name = "Interlace filter";
    return (f);
}

static void destroyinstance(struct filter *f)
{
    free(f->data);
    if (f->childimage != NULL)
        destroy_image(f->childimage);
    free(f);
}

static int doit(struct filter *f, int flags, int time)
{
    struct intdata *i = (struct intdata *)f->data;
    int val;
    if (!(f->req.flags & IMAGEDATA) &&
        f->childimage->currlines[0] == i->lastent)
        f->childimage->flip(f->childimage);
    i->lastent = f->childimage->currlines[0];
    val = f->previous->action->doit(f->previous, flags, time);
    if (i->first) {
        int y;
        for (y = 0; y < f->childimage->height; y++)
            memcpy(f->childimage->oldlines[y], f->childimage->currlines[y],
                   f->childimage->width * f->childimage->bytesperpixel);
        i->first = 0;
    }
    if (val & CHANGED)
        i->changed = 1, val |= ANIMATION;
    else {
        if (i->changed)
            val |= CHANGED;
        i->changed = 0;
    }
    return (val);
}

static void convertup(struct filter *f, int *x, int *y)
{
    *y *= 2;
    f->next->action->convertup(f->next, x, y);
}

static void convertdown(struct filter *f, int *x, int *y)
{
    *y /= 2;
    f->previous->action->convertdown(f->previous, x, y);
}

const struct filteraction interlace_filter = {
    "Interlace filter", "interlace", 0,           getinstance,
    destroyinstance,    doit,        requirement, initialize,
    convertup,          convertdown, NULL};
