#include "point.hpp"
#include "matrix.hpp"

#include <iostream>
#include <cmath>

using namespace visual_engine::detail::linalg;
using namespace visual_engine::detail::matrix;

bool point::is_valid() const { return (std::isfinite(x_) && std::isfinite(y_) && std::isfinite(z_)); }
void point::console_dump() const { std::cout << "pnt=(" << x_ << "," << y_ << "," << z_ << ")" << std::endl; }

size_t visual_engine::point::point_hasher::operator()(const point& p) const {
    using  hash = std::hash<linalg::coord_t>;
    return hash()(p.get_x()) ^ (hash()(p.get_x()) << 1) ^ (hash()(p.get_x()) << 3);
}

point::point(const vector& v) : x_(v.get_x()), y_(v.get_y()), z_(v.get_z()) {}

void point::move(const vector &v) {
    x_ = v.get_x() + x_;
    y_ = v.get_y() + y_;
    z_ = v.get_z() + z_;
}

void point::rotate(const point &p, const vector &v) {
    vector rot_vec = vector{*this} - vector{p};
    matrix_t<float> vec(rot_vec);
    // vec.dump();
    // matrix_t<float>::get_rotate_matix(v, v.length()).dump();
    matrix_t<float> new_vec(matrix_t<float>::get_rotate_matix(v, v.length()).product(vec));
    x_ = new_vec[0][0] + p.get_x();
    y_ = new_vec[1][0] + p.get_y();
    z_ = new_vec[2][0] + p.get_z();
}
