#pragma once

#include "../../../../include/dv-processing/core/frame/edge_map_accumulator.hpp"

#include <pybind11/pybind11.h>

namespace py = pybind11;

/**
 * @brief Bind EdgeMapAccumulator class to python
 * @param m pybind The module to bind to
 */
void bind_data_edge_map_accumulator(py::module &m) {
	using pybind11::operator""_a;
	py::class_<dv::EdgeMapAccumulator>(m, "EdgeMapAccumulator",
		"EdgeMapAccumulator accumulates events in a histogram representation with configurable contribution, but it is "
		"more efficient compared to generic accumulator since it uses 8-bit unsigned integers as internal memory type. "
		"The EdgeMapAccumulator behaves the same as a generic `dv::Accumulator` with STEP decay function, neutral and "
		"minimum value of 0.0, maximum value of 1.0 and configurable event contribution. The difference is that it "
		"doesn't use floating point numbers for the potential surface representation. The output data type of this "
		"accumulator is single channel 8-bit unsigned integer (CV_8UC1). Accumulation is performed using integer "
		"operations as well.")
		.def(py::init<const cv::Size &, const float, const bool, const float, const float>(), "resolution"_a,
			"contribution"_a = 0.25f, "ignorePolarity"_a = true, "neutralValue"_a = 0.f, "decay"_a = 1.f)
		.def("setIgnorePolarity", &dv::EdgeMapAccumulator::setIgnorePolarity, "ignorePolarity"_a,
			"Set ignore polarity option. All events are considered positive if enabled.")
		.def("isIgnorePolarity", &dv::EdgeMapAccumulator::isIgnorePolarity,
			"Check whether ignore polarity option is set to true.")
		.def("getNeutralPotential", &dv::EdgeMapAccumulator::getNeutralPotential,
			"Get the neutral potential value for the accumulator. The range for potential value is [0.0; 1.0], where "
			"1.0 stands for maximum possible potential - 255 in 8-bit pixel representation.")
		.def("setNeutralPotential", &dv::EdgeMapAccumulator::setNeutralPotential, "neutralValue"_a,
			"Set the neutral potential value. The value should be in range 0.0 to 1.0, other values will be clamped to "
			"this range.")
		.def("getDecay", &dv::EdgeMapAccumulator::getDecay, "Get current decay value.")
		.def("setDecay", &dv::EdgeMapAccumulator::setDecay, "decay"_a,
			"Set the decay value. Decay value is clamped to range of [0.0; 1.0].")
		.def("reset", &dv::EdgeMapAccumulator::reset, "Clear the buffered events.")
		.def("setEventContribution", &dv::EdgeMapAccumulator::setEventContribution, py::arg("contribution"),
			"Set new contribution coefficient.")
		.def("getEventContribution", &dv::EdgeMapAccumulator::getEventContribution,
			"Get the contribution coefficient for a single event. The contribution value is multiplied by the maximum "
			"possible pixel value (255) to get the increment value. E.g. contribution value of 0.1 will increment a "
			"pixel value at a single event coordinates by 26.")
		.def(
			"accept",
			[](dv::EdgeMapAccumulator &self, const dv::EventStore &events) {
				self.accept(events);
			},
			py::arg("events"), "Add events to the accumulator")
		.def(
			"generateFrame",
			[](dv::EdgeMapAccumulator &self) -> dv::Frame {
				return self.generateFrame();
			},
			"Generates the accumulation frame (potential surface) at the time of the last consumed event. The function "
			"writes the output image into the given `outFrame` argument. The output frame will contain data with type "
			"CV_8UC1. The function resets any events accumulated up to this function call.");
}
