// Copyright 2024 SquareBlock Inc. All Rights Reserved.
// Author: tianlei.richard@qq.com (tianlei.richard)

#include "texture.h"
#include "spdlog/spdlog.h"
#include "util/interpolation.h"
#include <opencv2/highgui/highgui.hpp>

Texture::Texture(const std::filesystem::path &texture_path) {
  if (!std::filesystem::exists(texture_path)) {
    spdlog::warn("Texture {} is not existed!", texture_path.c_str());
    throw std::filesystem::filesystem_error("File not found",
                                            std::error_code{});
  }
  texture_ = (cv::imread(texture_path));
  spdlog::debug("Texture at {}, shape: ({},{})", texture_path.c_str(),
                texture_.cols, texture_.rows);
}

cv::Vec3b Texture::sample(const Point2d &texture_coordinate) {
  cv::Vec3b res{0, 0, 0};

  const double x = texture_coordinate.x() * texture_.cols - 0.5;
  const double y = texture_coordinate.y() * texture_.rows - 0.5;

  const int x_f = x;
  const int x_c = x + 1.;
  const float t_x = x - x_f;
  const int y_f = y;
  const int y_c = y + 1.;
  const float t_y = y - y_f;

  const cv::Vec3b &a = texture_.at<cv::Vec3b>(x_f, y_f);
  const cv::Vec3b &b = texture_.at<cv::Vec3b>(x_f, y_c);
  const cv::Vec3b &c = texture_.at<cv::Vec3b>(x_c, y_f);
  const cv::Vec3b &d = texture_.at<cv::Vec3b>(x_c, y_c);

  res = bilerp(t_x, t_y, a, b, c, d);

  return res;
}
