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

#include "triangle.h"
#include <algorithm>
#include <iostream>

Triangle::Triangle(const Point3d &a, unsigned int idx_a, const Point3d &b,
                   unsigned int idx_b, const Point3d &c, unsigned int idx_c)
    : indices_({idx_a, idx_b, idx_c}), vertices_({a, b, c}) {}

Triangle::Triangle(const std::vector<std::shared_ptr<Vertex>> &vertices,
                   unsigned int idx_a, unsigned int idx_b, unsigned int idx_c)
    : indices_({idx_a, idx_b, idx_c}),
      vertices_({(vertices[idx_a])->position, (vertices[idx_b])->position,
                 (vertices[idx_c])->position}) {}

std::vector<unsigned int> Triangle::get_vertex_index() const {
  return {indices_[0], indices_[1], indices_[2]};
}

std::vector<Point3d> Triangle::get_vertex_position() const {
  return std::vector<Point3d>{
      vertices_[0],
      vertices_[1],
      vertices_[2],
  };
}

void Triangle::set_points(const std::vector<Point3d> &points) {
  vertices_[0] = points[0];
  vertices_[1] = points[1];
  vertices_[2] = points[2];
}

BBox Triangle::axis_align_bbox() const {
  const int x_min =
      std::min({vertices_[0].x(), vertices_[1].x(), vertices_[2].x()});
  const int y_min =
      std::min({vertices_[0].y(), vertices_[1].y(), vertices_[2].y()});
  const int x_max =
      std::max({vertices_[0].x(), vertices_[1].x(), vertices_[2].x()});
  const int y_max =
      std::max({vertices_[0].y(), vertices_[1].y(), vertices_[2].y()});
  return BBox{x_min, y_min, (x_max - x_min + 1), (y_max - y_min + 1)};
}

Vector3d Triangle::normal_vector() const {
  const auto v1 = vertices_[1] - vertices_[0];
  const auto v2 = vertices_[2] - vertices_[1];
  return v1.cross(v2).normalized();
}
