/* bmp.c */
#include <bmp.h>
#include <omnistd.h>

extern rgb **globalcolors;

bitmap *parsebmp(int8 *bmpfile, int16 x, int16 y) {
    bitmap *bm;
    int16 size, n;
    bitmapheader *hdr;
    infoheader *info;
    colortable *colors;
    int16 fd;
    int8 *filename;
    int8 *file, *p;

    if (!bmpfile)
        return (bitmap *)0;
    
    filename = addbmp(bmpfile);
    fd = open(filename, 0);
    if (!fd)
        return (bitmap *)0;
    
    file = (int8 *)alloc(128);
    if (!file) {
        close(fd);
        return (bitmap *)0;
    }
    zero($1 file, $2 128);

    for (n=BmpHdrSz, p=file; n; n--, p++)
        *p = read(fd);
    close(fd);
    
    hdr = (bitmapheader *)file;
    size = sizeof(struct s_bitmapheader);
    info = (infoheader *)(file+size);
    size = sizeof(colortable);
    colors = (colortable *)alloc(size);
    if (!colors)
        return (bitmap *)0;
    
    n = sizeof(struct s_bitmapheader)
        + sizeof(struct s_infoheader);
    copy($1 colors, $1 (file+n), size);

    size = sizeof(struct s_bitmap);
    bm = (bitmap *)alloc(size);
    if (!bm)
        return (bitmap *)0;
    
    bm->x = x;
    bm->y = y;
    bm->hdr = hdr;
    bm->info = info;
    bm->colors = colors;
    bm->filename = filename;
    
    return bm;
}

boolean drawbmp(bitmap *bm) {
    int16 size;
    int16 width;
    int8 byte, bithigh, bitlow;
    int16 n;
    point *pp;
    int16 line, cols;
    int16 fd;
    int8 *file;

    if (!bm)
        return false;

    file = bm->filename;
    fd = open(file, bm->hdr->offset);
    if (!fd)
        return false;

    size = (bm->info->height*bm->info->width)/2;
    if ((bm->info->height*bm->info->width)%2)
        size++;
    width = (bm->info->width/2);

    save();
    // line = cols = 0;
    cols = 0;
    line = bm->info->height;

    for (n=size; n; n--) {
        if (!(n%width)) {
            line--;
            cols = 0;
        }

        byte = read(fd);
        // if (!byte) {
        //     close(fd);
        //     return true;
        // }
        bitlow = (byte & 0x0f);
        bithigh = ((byte & 0xf0) >> 4);

        // pp = mkpoint((cols+bm->x), (line+bm->y), getclr(bm, bithigh));
        pp = mkpoint((cols+bm->x),
            // (line+bm->y), getclr(bm->colors, bithigh));
            (line+bm->y), bithigh);
        if (pp)
            drawpoint(pp);

        // pp = mkpoint((cols+bm->x), (line+bm->y),
        //     getclr(bm->colors, bitlow));
        pp = mkpoint((cols+bm->x),
            // (line+bm->y), getclr(bm->colors, bitlow));
            (line+bm->y), bitlow);
        if (pp)
            drawpoint(pp);

        cols++;
        load();
   }
   close(fd);

    return true;
}

int8 getclr(colortable *colors, int8 input) {
    int8 red, green, blue;
    int8 red_, green_, blue_;
    int8 ret;
    int16 n, mix;
    int8 mix_;

    for (ret=n=0; n<256; n++) {
        red = ((globalcolors[n]->red & 0xf0) >> 4);
        green = ((globalcolors[n]->green & 0xf0) >> 4);
        blue = ((globalcolors[n]->blue & 0xf0) >> 4);

        red_ = colors[input]->red;
        green_ = colors[input]->green;
        blue_ = colors[input]->blue;

        mix = $2 ((red_ + green_ + blue_) / 3);
        mix_ = (int8)((mix & 0xf0) >> 4);
        red_ = green_ = blue_ = mix_;

        if (false) {
            printf("(%x/%x) ", n, $2 input);
            printf("#%x%x%x <>", red, green, blue);
            printf(" #%x%x%x", red_, green_, blue_);
        }

        if (
            (red == red_)
            && (green == green_)
            && (blue == blue_)) {
                if (false)
                    printf("%c", (int8)'*');

                ret = n;
                break;
            }
        if (false) {
            printf("%c", (int8)'\t');
            getchar();
        }
    }

    return n;
}

int8 *addbmp(int8 *file) {
    int8 *ret, *p;
    int16 size;

    if (!file)
        return $1 0;
    
    size = stringlen(file);
    if (!size)
        return $1 0;
    ret = $1 alloc(16);
    if (!ret)
        return $1 0;
    zero($1 ret, 16);
    stringcopy($1 ret, $1 file, size);
    p = ret + size;
    stringcopy($1 p, $1 ".bmp", 4);

    return ret;
}

int8 *showbitmap_(int8 *var, bitmap *bm) {
    int8 *p, *buf;
    int8 tmp[BufSz];
    int16 bytes;
    int8 x, n;

    if (!bm || !var)
        return $1 0;
    
    n = BufSz;
    buf = $1 alloc($2 n);
    if (!buf)
        return buf;
    zero(buf, $2 n);
    zero(tmp, $2 n);
    p = buf;

    bytes = 0;
    showrecord("bitmap *%s = {\n", var);
    showrecord("  filename:\t %s\n", bm->filename);
    showrecord("  x:\t\t 0x%x\n", bm->x);
    showrecord("  y:\t\t 0x%x\n", bm->y);
    showrecord("  signature:\t 0x%x\n", bm->hdr->signature);
    showrecord("  size:\t\t 0x%x\n", bm->hdr->size);
    showrecord("  offset:\t 0x%x\n", bm->hdr->offset);
    showrecord("  width:\t 0x%x\n", bm->info->width);
    showrecord("  height:\t 0x%x\n", bm->info->height);
    showrecord("  # colors:\t 0x%x\n", bm->info->numcolors);
    showrecord("%s\n", $1 "}");

    printf("%s\n", $1 "colortable *colors = {");
    for (x=0; x<16; x++)
        printf("  [0x%x]:\t #%x.%x.%x\n", x,
            bm->colors[x]->red,
            bm->colors[x]->green,
            bm->colors[x]->blue
        );
    printf("%s\n", $1 "}");
    *p = 0;

    return buf;
}
