#pragma once
#include "vertex.hpp"
#include "img.hpp"
#include "object.hpp"
#include "scene.hpp"
#include "common.hpp"
#include <vector>


class ShaderInfo {
    public:
        typedef struct {
            ray_t ray;
            vertex_t ray_normal;
            vertex_t hitpoint;
            vertex_t normal;
            const Object* object;
            coord_t depth;
        } shader_info_t;

    private:
        shader_info_t* const buf;

    public:
        const unsigned w, h;

        ShaderInfo(unsigned, unsigned);
        ~ShaderInfo();
        void reset();

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

};


class PixelShader {
    private:
        static std::vector<PixelShader*> insts;

    public:
        PixelShader();
        virtual ~PixelShader();
        virtual void get(const Scene*, ShaderInfo::shader_info_t&, Img::rgb_t&) const = 0;
        static void get_all(const Scene*, ShaderInfo::shader_info_t&, Img::rgb_t&);
        static void clear_all();
};


class ImageShader {
    private:
        static std::vector<ImageShader*> insts;

    public:
        ImageShader();
        virtual ~ImageShader();
        virtual void get(const Scene*, ShaderInfo&, Img&) const = 0;
        static bool get_all(const Scene*, ShaderInfo&, Img&);
        static void clear_all();
};