#include "camera.hpp"
#include "mesh.hpp"
#include "share.hpp"
#include "vector.hpp"
#include <iostream>

using namespace visual_engine::detail;
using namespace visual_engine;

void camera::console_dump() const {
    std::cout << "CAM:" << std::endl;
    std::cout << "pos=";
    pos_.console_dump();
    std::cout << "dirx=";
    dir_x_.console_dump();
    std::cout << "diry=";
    dir_y_.console_dump();
    std::cout << "cols=" << grid_.cols_ << std::endl;
    std::cout << "rows=" << grid_.rows_ << std::endl;
    std::cout << "viewport distance=" << grid_.viewport_distance_ << std::endl;
    std::cout << "grid:" << std::endl;
    for (auto&& i : grid_.vec_grid_)
        i.console_dump();
    std::cout << std::endl;
}

void camera::render() {
    frame_buffer_.clear();
    auto it = grid_.vec_grid_.begin();
    for (int i = 0; i != grid_.rows_; ++i)
        for (int j = 0; j != grid_.cols_; ++j, ++it) {
            double t = get_best_intersection_scene(*it);
            frame_buffer_.push_back(get_ascii_for_cos(t));
        }
}

using paircd = std::pair<coord_t, double>;
double camera::get_best_intersection_scene(const vector& v) const {
    paircd best(0,0);
    for (mesh m: *objects_) {
        auto a = m.get_best_line_intersection_mesh(pos_, v, 0.5);
        if (!a.has_value()) continue;
        if (best == paircd{0,0} || best.first > a.value().first)
            best = a.value();
    }
    if (best == paircd{0,0}) return 0;
    return best.second;
}

char camera::get_ascii_for_cos(double t) {
    char symbols[] = {' ', '.', ',', ':', ';', '*', 'o', '#', '%','@', '@'};
    int tmp = (int)(-t * 10);
    return symbols[tmp];
}

void camera::show() const { std::cout << frame_buffer_ << std::endl; }

void camera::move(const vector& v) {
    // vector dirz = dir_y_.product(dir_x_);
    // vector begin_vec = (dirz   *  vp_dist)                     -
    //                     (x_step * ((coord_t)(cols_term-1) / 2)) +
    //                     (y_step * ((coord_t)(rows_term-1) / 2));
    // for (int i = 0; i != rows_term; ++i)
    //     for (int j = 0; j != cols_term; ++j)
    //         grid_.vec_grid_.push_back((begin_vec + j*x_step - i*y_step).normalized());
    // @TODO сделать фазу рендера когда происходит это

    pos_ = point{vector{pos_} + v};
}
