#pragma once

#include "../../../../include/dv-processing/camera/calibrations/imu_calibration.hpp"

#include <pybind11/pybind11.h>

namespace py = pybind11;

/**
 * @brief Bind camera::calibrations::IMUCalibration to python
 * @param m pybind The module to bind to
 */
void bind_calibration_imu_calibration(py::module &m) {
	using pybind11::operator""_a;

	py::class_<dv::camera::calibrations::IMUCalibration> imuCalibration(m, "IMUCalibration");

	py::class_<dv::camera::calibrations::IMUCalibration::Metadata>(imuCalibration, "Metadata")
		.def(py::init<const std::string &, const std::string &>(), py::arg("calibrationTime") = "",
			py::arg("comment") = "")
		.def_readonly("calibrationTime", &dv::camera::calibrations::IMUCalibration::Metadata::calibrationTime,
			"Timestamp when the calibration was conducted")
		.def_readonly(
			"comment", &dv::camera::calibrations::IMUCalibration::Metadata::comment, "Any additional information");

	imuCalibration.def(py::init<>())
		.def(py::init<const std::string &, float, float, const cv::Point3f &, const cv::Point3f &, float, float, float,
				 float, float, float, float, const dv::kinematics::Transformationf &,
				 const std::optional<dv::camera::calibrations::IMUCalibration::Metadata> &>(),
			py::arg("name"), py::arg("omegaMax"), py::arg("accMax"), py::arg("omegaOffsetAvg"), py::arg("accOffsetAvg"),
			py::arg("omegaOffsetVar"), py::arg("accOffsetVar"), py::arg("omegaNoiseDensity"),
			py::arg("accNoiseDensity"), py::arg("omegaNoiseRandomWalk"), py::arg("accNoiseRandomWalk"),
			py::arg("timeOffset"), py::arg("transformationToC0"), py::arg("metadata"))
		.def_readonly(
			"name", &dv::camera::calibrations::IMUCalibration::name, "Sensor name (e.g. 'IMU_DVXplorer_DXA02137')")
		.def_readonly("omegaMax", &dv::camera::calibrations::IMUCalibration::omegaMax,
			"Maximum (saturation) angular velocity of the gyroscope [rad/s]")
		.def_readonly("accMax", &dv::camera::calibrations::IMUCalibration::accMax,
			"Maximum (saturation) acceleration of the accelerometer [m/s^2]")
		.def_readonly("omegaOffsetAvg", &dv::camera::calibrations::IMUCalibration::omegaOffsetAvg,
			"Average offset (bias) of the angular velocity [rad/s]")
		.def_readonly("accOffsetAvg", &dv::camera::calibrations::IMUCalibration::accOffsetAvg,
			"Average offset (bias) of the acceleration [m/s^2]")
		.def_readonly("omegaOffsetVar", &dv::camera::calibrations::IMUCalibration::omegaOffsetVar,
			"Variance of the offset of the angular velocity [rad/s]")
		.def_readonly("accOffsetVar", &dv::camera::calibrations::IMUCalibration::accOffsetVar,
			"Variance of the offset of the acceleration [m/s^2]")
		.def_readonly("omegaNoiseDensity", &dv::camera::calibrations::IMUCalibration::omegaNoiseDensity,
			"Noise density of the gyroscope [rad/s^s/sqrt(Hz)]")
		.def_readonly("accNoiseDensity", &dv::camera::calibrations::IMUCalibration::accNoiseDensity,
			"Noise density of the accelerometer [m/s^2/sqrt(Hz)]")
		.def_readonly("omegaNoiseRandomWalk", &dv::camera::calibrations::IMUCalibration::omegaNoiseRandomWalk,
			"Noise random walk of the gyroscope [rad/s^s/sqrt(Hz)]")
		.def_readonly("accNoiseRandomWalk", &dv::camera::calibrations::IMUCalibration::accNoiseRandomWalk,
			"Noise random walk of the accelerometer [m/s^2/sqrt(Hz)]")
		.def_readonly("timeOffsetMicros", &dv::camera::calibrations::IMUCalibration::timeOffsetMicros,
			"Offset between the camera and IMU timestamps in microseconds (t_correct = t_imu - offset)")
		.def_readonly("transformationToC0", &dv::camera::calibrations::IMUCalibration::transformationToC0,
			"Transformation converting points in IMU frame to C0 frame p_C0= T * p_IMU")
		.def_readonly("metadata", &dv::camera::calibrations::IMUCalibration::metadata, "Metadata");
}
