#include "dv-processing/data/depth_event_base.hpp"

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

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

namespace py = pybind11;

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

	// Bind dv::DepthEvent
	py::class_<dv::DepthEvent>(m, "DepthEvent")
		.def(py::init<const int64_t, int16_t, int16_t, bool, uint16_t>(), py::arg("timestamp"), py::arg("x"),
			py::arg("y"), py::arg("polarity"), py::arg("depth"))
		.def("timestamp", &dv::DepthEvent::timestamp, "Microsecond timestamp of the captured event")
		.def("x", &dv::DepthEvent::x, "X coordinate")
		.def("y", &dv::DepthEvent::y, "Y coordinate")
		.def("polarity", &dv::DepthEvent::polarity,
			"Polarity value, True for increase of brightness, False for decrease")
		.def("depth", &dv::DepthEvent::depth, "Depth value in millimeters")
		.def(
			"time",
			[](const dv::DepthEvent &self) {
				return dv::toTimePoint(self.timestamp());
			},
			"Timestamp of the captured data, compatible with python time library");

	// Bind dv::DepthEventPacket
	auto depthEventPacketClass = py::class_<dv::DepthEventPacket>(m, "DepthEventPacket");
	py::bind_vector<std::vector<dv::DepthEvent>>(depthEventPacketClass, "DepthEventVector");

	depthEventPacketClass.def(py::init<>())
		.def(py::init<const std::vector<dv::DepthEvent> &>(), "depthEvents"_a,
			"Create a depth event packet from list of depth events")
		.def_readwrite("elements", &dv::DepthEventPacket::elements)
		.def("numpy",
			[](const dv::DepthEventPacket &self) {
				py::list names;
				names.append("timestamp");
				names.append("x");
				names.append("y");
				names.append("polarity");
				names.append("depth");
				py::list formats;
				formats.append("<i8");
				formats.append("<i2");
				formats.append("<i2");
				formats.append("<i1");
				formats.append("<u2");
				py::list offsets;
				offsets.append(0);
				offsets.append(8);
				offsets.append(10);
				offsets.append(12);
				offsets.append(14);
				return py::array(
					py::dtype(names, formats, offsets, sizeof(dv::Event)), self.elements.size(), self.elements.data());
			})
		.def_static("GetFullyQualifiedName", &dv::DepthEventPacket::GetFullyQualifiedName)
		.def_static("PacketIdentifier", &dv::DepthEventPacketIdentifier);
	py::implicitly_convertible<std::vector<dv::DepthEvent>, dv::DepthEventPacket>();
}
