#pragma once
#include "common.hpp"
#include "vertex.hpp"


class Img {
    public:
        typedef unsigned char val_t;
        typedef struct __attribute__((packed)) rgb_s {
#ifdef USE_X
            // suitable for X11 TrueColor image
            val_t b, g, r;
            val_t x; // unused
            rgb_s(): b(0), g(0), r(0), x(0) {}
            rgb_s(val_t rr, val_t gg, val_t bb): b(bb), g(gg), r(rr), x(0) {}
#else
            // can be optimized for PPM bitmap files
            val_t r, g, b;
            rgb_s(): r(0), g(0), b(0) {}
            rgb_s(val_t rr, val_t gg, val_t bb): r(rr), g(gg), b(bb) {}
#endif
            INLINE rgb_s& operator*=(coord_t o) {
                r *= o;
                g *= o;
                b *= o;
                return *this;
            }
            void debug(const char* prefix) {
                LOG("%s0x%02x%02x%02x", prefix?:"", r, g, b);
            }
        } rgb_t;

    private:
        rgb_t* const buf;
        void* const freebuf;

        bool to_ppm(int) const;

    public:
        const unsigned w, h;

        Img(unsigned, unsigned);
        Img(unsigned, unsigned, rgb_t*, void*);
        ~Img();

        INLINE rgb_t& at(unsigned x, unsigned y) {
            assert(x < w && y < h);
            return buf[(y*w)+x];
        }

        INLINE const rgb_t& at(unsigned x, unsigned y) const {
            assert(x < w && y < h);
            return buf[(y*w)+x];
        }

        rgb_t avg(unsigned, unsigned, unsigned, unsigned) const;
        rgb_t interpolate(coord_t, coord_t) const;

        static Img* from_ppm(const char*);
        bool to_ppm(const char*) const;

        bool supersample(unsigned, Img*) const;
        Img* rotate() const;
        void mirror_x();
        void mirror_y();
};