#include "../../include/dv-sdk/module.hpp"

#include <array>
#include <vector>

struct pixel_with_count {
	int16_t x;
	int16_t y;
	int32_t count;

	pixel_with_count(int16_t _x, int16_t _y) : x(_x), y(_y), count(0) {
	}

	pixel_with_count(int16_t _x, int16_t _y, int32_t _count) : x(_x), y(_y), count(_count) {
	}
};

#define GET_TS(X)          static_cast<int64_t>((X) >> 1)
#define GET_POL(X)         static_cast<bool>((X) & 0x01)
#define SET_TSPOL(TS, POL) ((static_cast<int64_t>(TS) << 1) | (static_cast<int64_t>(POL) & 0x01))

class DVSNoiseFilter : public dv::ModuleBase {
public:
	static void initInputs(dv::InputDefinitionList &in);

	static void initOutputs(dv::OutputDefinitionList &out);

	static const char *initDescription();

	static void initConfigOptions(dv::RuntimeConfig &config);

	DVSNoiseFilter();

	void run() override;

	void configUpdate() override;

private:
	// Hot Pixel filter (learning).
	bool hotPixelLearningStarted;
	int64_t hotPixelLearningStartTime;
	std::vector<int32_t> hotPixelLearningMap;
	// Hot Pixel filter (filtering).
	std::vector<pixel_with_count> hotPixelArray;
	int64_t hotPixelStatOn;
	int64_t hotPixelStatOff;
	// Background Activity filter.
	std::array<size_t, 8> supportPixelIndexes;
	int64_t backgroundActivityStatOn;
	int64_t backgroundActivityStatOff;
	// Refractory Period filter.
	int64_t refractoryPeriodStatOn;
	int64_t refractoryPeriodStatOff;
	// Maps and their sizes.
	int16_t sizeX;
	int16_t sizeY;
	std::vector<int64_t> timestampsMap;

	inline size_t doBackgroundActivityLookup(int16_t x, int16_t y, size_t pixelIndex, int64_t timestamp, bool polarity,
		size_t *supportIndexes, int32_t backgroundActivityTime, bool backgroundActivityCheckPolarity);

	void hotPixelGenerateArray();
	void hotPixelLoadConfig();
};

registerModuleClass(DVSNoiseFilter)
