#ifndef LINALG_TRIANGLE_HPP
#define LINALG_TRIANGLE_HPP

#include "share.hpp"
#include "point.hpp"
#include "vector.hpp"

#include <optional>
#include <vector>

namespace visual_engine {
namespace detail {
namespace linalg {

class triangle_ final {
    point_position a_, b_, c_;
    vector norm_;

public:
    triangle_(const point_position a, const point_position b, const point_position c, const vector& n) : a_(a), b_(b), c_(c), norm_(n) {}
    std::optional<float> line_intersect_triag_param(const std::vector<point> &p_buff, const point &p, const vector &v) const;
    void console_dump() const;
    vector         get_norm()  const { return norm_; }
    point_position get_point() const { return a_;    }
    void norm_rotate(const vector &v);

private:
    std::optional<float> line_intersect_with_triag_plane_param(const std::vector<point> &p_buff, const point &p, const vector &v) const;
    bool is_in_triag(const std::vector<point> &p_buff, const point &p, const vector &v, float t) const;
    bool all_by_one_side(const vector& v1, const vector& v2, const vector& v3) const;
};

class triangle final {
    point a_, b_, c_;
    vector norm_;

public:
    triangle(const point& a, const point& b, const point& c, const vector& norm) : a_(a), b_(b), c_(c), norm_(norm) {}
    const point&  get_a()    const { return a_;    }
    const point&  get_b()    const { return b_;    }
    const point&  get_c()    const { return c_;    }
    const vector& get_norm() const { return norm_; }
};

// std::optional<double> line_intersect_triag_param(const std::vector<point> &p_buff, const triangle_ &tr, const point &p, const vector &v);

} // namespace linalg
} // namespace detail

using detail::linalg::triangle;

} // namespace visual_engine

#endif // LINALG_TRIANGLE_HPP
