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


class Object {
    protected:
        mutable LightMap* lightmap;

        static bool quadfunc(const coord_t& a, const coord_t& b, const coord_t& c, coord_t& t);
        static void lincomb(const vertex_t& P, coord_t& a, const vertex_t& A, coord_t& b, const vertex_t& B);

    public:
        typedef struct {
            coord_t a, b;
        } intersect_ctx_t;

        const Texture* const tex;
        const bool sided;

        const vertex_t bound_min, bound_max, bound_center, bound_cdiag;

        Object(Texture* t, bool, const vertex_t bmin, const vertex_t bmax);
        virtual ~Object();

        virtual bool intersect(const ray_t&) const = 0;
        virtual bool intersect(intersect_ctx_t&, const ray_t&, const vertex_t& raynrm, vertex_t& rv) const = 0;
        virtual void intersect(intersect_ctx_t&, const ray_t&, const vertex_t& rv, vertex_t& nrm, LightValue&, Img::rgb_t*) const = 0;

        virtual coord_t sqdist(const vertex_t&, coord_t, coord_t) const = 0;

        bool intersect_box(const vertex_t& rmin, const vertex_t& rmax) const;
        bool intersect_box(const vertex_t& rmin, const vertex_t& rmax, coord_t) const;
        static bool intersect_box(const vertex_t&, const vertex_t&, const vertex_t&, const vertex_t&);

        virtual void from_uv(coord_t u, coord_t v, vertex_t& rv, vertex_t& nrm) const = 0;
        vertex_t from_uv(coord_t u, coord_t v) const;
        virtual void max_uv(coord_t&, coord_t&) const = 0;
        void max_dim(unsigned&, unsigned&) const;
        void set_lightmap(LightMap*) const; // mutable
};