#pragma once

#include "../../../include/dv-processing/core/time.hpp"
#include "../../../include/dv-processing/data/timed_keypoint_base.hpp"

#include <pybind11/pybind11.h>
#include <pybind11/stl_bind.h>

PYBIND11_MAKE_OPAQUE(std::vector<dv::TimedKeyPoint>)

namespace py = pybind11;

/**
 * @brief Bind TimedKeyPoint and TimedKeyPointPacket class to python
 * @param m pybind The module to bind to
 */
void bind_timed_keypoint_base(py::module &m) {
	using pybind11::operator""_a;

	py::class_<dv::TimedKeyPoint>(m, "TimedKeyPoint")
		.def(py::init<const dv::Point2f &, float, float, float, int32_t, int32_t, int64_t>(), py::arg("pt"),
			py::arg("size"), py::arg("angle"), py::arg("response"), py::arg("octave"), py::arg("class_id"),
			py::arg("timestamp"))
		.def_readwrite("pt", &dv::TimedKeyPoint::pt, "Coordinates of the keypoint.")
		.def_readwrite("size", &dv::TimedKeyPoint::size, "Diameter of the meaningful keypoint neighborhood.")
		.def_readwrite("angle", &dv::TimedKeyPoint::angle,
			"computed orientation of the keypoint (-1 if not applicable); it's in [0,360) degrees and measured "
			"relative to image coordinate system, ie in clockwise.")
		.def_readwrite("response", &dv::TimedKeyPoint::response,
			"The response by which the most strong keypoints have been selected. Can be used for the further sorting "
			"or subsampling.")
		.def_readwrite(
			"octave", &dv::TimedKeyPoint::octave, "Octave (pyramid layer) from which the keypoint has been extracted.")
		.def_readwrite("class_id", &dv::TimedKeyPoint::class_id,
			"Object class (if the keypoints need to be clustered by an object they belong to).")
		.def_readwrite("timestamp", &dv::TimedKeyPoint::timestamp, "Timestamp (µs).")
		.def(
			"time",
			[](const dv::TimedKeyPoint &self) {
				return dv::toTimePoint(self.timestamp);
			},
			"Timestamp of the captured data, compatible with python time library");

	py::class_<dv::TimedKeyPointPacket> timedKeypointPacketClass(m, "TimedKeyPointPacket");
	py::bind_vector<std::vector<dv::TimedKeyPoint>>(timedKeypointPacketClass, "TimedKeyPointVector");

	timedKeypointPacketClass.def(py::init<>())
		.def(py::init<const std::vector<dv::TimedKeyPoint> &>(), "timedKeypoints"_a,
			"Create a packet from a list of timed keypoints")
		.def_readwrite("elements", &dv::TimedKeyPointPacket::elements)
		.def_static("GetFullyQualifiedName", &dv::TimedKeyPointPacket::GetFullyQualifiedName)
		.def_static("PacketIdentifier", &dv::TimedKeyPointPacketIdentifier);

	py::implicitly_convertible<std::vector<dv::TimedKeyPoint>, dv::TimedKeyPointPacket>();
}
