#pragma once
#include <memory>
#include "viewport.hpp"


/**
 * @file
 * @brief Ray-tracing.
 */


/** @brief Follow camera rays to raster, determine @ref Object hit points. */
class Tracer {
  private:
    ThreadQueue<context_t>& next;
    ThreadQueue<context_t> thread;
    ThreadPool<context_t, 4> threads;

    void trace(std::unique_ptr<context_t>&&);
    static void trace_corner(context_t*, size_t);
    static INLINE void do_trace(ray_t&, box_t&, trace_px_t&, std::list<const Object*>&);

  public:
    Tracer(ThreadQueue<context_t>& next);

    ThreadQueue<context_t>& queue();
};


/** @brief For @ref Tracer hit points, determine light values by tracing @ref PointLight sources. */
class LightTracer {
  private:
    ThreadQueue<context_t>& next;
    ThreadQueue<context_t> thread;
    ThreadPool<context_t, 4> threads;

    void trace(std::unique_ptr<context_t>&&);
    static void trace_corner(context_t*, size_t);
    static INLINE void do_trace(const trace_px_t&, fcoord_t, std::list<const Object*>&, const std::list<lightbox_t>&,
                                vertex_t&);

  public:
    LightTracer(ThreadQueue<context_t>& next);

    ThreadQueue<context_t>& queue();
};