/**
* \Spherical FIR Table Definitions
*
* \brief Declaration of Spherical FIR Table Definitions class interface
* \date	July 2023
*
* \authors 3DI-DIANA Research Group (University of Malaga), in alphabetical order: M. Cuevas-Rodriguez, D. Gonzalez-Toledo, L. Molina-Tanco, F. Morales-Benitez ||
* Coordinated by , A. Reyes-Lecuona (University of Malaga)||
* \b Contact: areyes@uma.es
*
* \b Copyright: University of Malaga
* 
* \b Contributions: (additional authors/contributors can be added here)
*
* \b Project: 3D Tune-In (https://www.3dtunein.eu) and SONICOM (https://www.sonicom.eu/) ||
*
* \b Acknowledgement: This project has received funding from the European Union's Horizon 2020 research and innovation programme under grant agreements no. 644051 and no. 101017743
* 
* This class is part of the Binaural Rendering Toolbox (BRT), coordinated by A. Reyes-Lecuona (areyes@uma.es) and L. Picinali (l.picinali@imperial.ac.uk)
* Code based in the 3DTI Toolkit library (https://github.com/3DTune-In/3dti_AudioToolkit).
* 
* \b Licence: This program is free software, you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
*/


#ifndef _CSPHERICAL_FIR_TABLE_DEFINITIONS_HPP
#define _CSPHERICAL_FIR_TABLE_DEFINITIONS_HPP

#include <unordered_map>
#include <vector>
#include <utility>
#include <list>
#include <cstdint>
#include <Common/Buffer.hpp>
#include <Common/ErrorHandler.hpp>
#include <Common/CommonDefinitions.hpp>
#include <Common/GlobalParameters.hpp>
#include <ServiceModules/ServicesBase.hpp>
#include <ServiceModules/SphericalSearchKDTree.hpp>

namespace BRTServices {


#ifndef PI 
#define PI 3.14159265
#endif
#ifndef DEFAULT_RESAMPLING_STEP
#define DEFAULT_GRIDSAMPLING_STEP 5
#endif

#ifndef DEFAULT_HRTF_MEASURED_DISTANCE
#define DEFAULT_HRTF_MEASURED_DISTANCE 1.95f	//TO be deleted
#endif

#ifndef DEFAULT_EXTRAPOLATION_STEP
#define DEFAULT_EXTRAPOLATION_STEP 10
#endif

	
			
	////////////////////////////////////////////////////
	// SOFA Table definitions
	///////////////////////////////////////////////////	
	struct TSofaDataBucket {		
		Common::CVector3 referencePosition;		
		BRTServices::TIRStruct data;
	};	
	using TRawSofaData = std::vector<TSofaDataBucket>;
	
	// Spherical FIR Table definitions
	//using TSphericalFIRTable = std::unordered_map<TOrientation_key, BRTServices::TIRStruct>;	// Base
	
	///////////////////////////////////////////////////
	//// Spherical Partitioned FIR Table definitions
	////////////////////////////////////////////////////
	 	
	// IR Table ordered by orientation
	using TSphericalFIRTablePartitioned = std::unordered_map<TOrientation_key, BRTServices::TFRPartitionedStruct>;
	
	// One distance bucket: one sphere (same distance), many directions
	struct TDistanceBucket {
		int32_t distance_mm = 0;
		CSphericalSearchKDTree<TOrientation> searchTree;
		TSphericalFIRTablePartitioned table;
	};

	// One reference position bucket: multiple distances
	struct TReferenceBucket {
		TVector3_key referenceKey;
		Common::CVector3 referencePos;
		std::vector<TDistanceBucket> distances;
	};
	
	// Spherical FIR Table Map - Reference position bucket map
	using TReferenceBucketMap  = std::unordered_map<TVector3_key, TReferenceBucket>;

	
	////////////////////////////////////////
	// Fast lookup by exact reference key
	/////////////////////////////////////////

	// Small list to do nearest-reference search
	struct TReferenceEntry
	{
		TVector3_key key;
		int32_t x_mm = 0;
		int32_t y_mm = 0;
		int32_t z_mm = 0;

		TReferenceEntry() = default;
		TReferenceEntry(const TVector3_key& _key, int32_t _x_mm, int32_t _y_mm, int32_t _z_mm)
			: key{ _key }
			, x_mm{ _x_mm }
			, y_mm{ _y_mm }
			, z_mm{ _z_mm } { }
	};
	using TReferenceEntryList = std::vector<TReferenceEntry>;


	///////////////////////////////////////////////////
	/// Spherical Interpolated FIR Table definitions
	//////////////////////////////////////////////////
	
	//using TRawSofaTable = std::unordered_map<TOrientation, BRTServices::THRIRStruct>;
	using TRawSofaTable = std::unordered_map<TOrientation, BRTServices::TIRStruct>;

	struct TDistanceBucketRawSofa {	
		double distance = 0.0;
		int32_t distance_mm = 0;
		TRawSofaTable table;
	};
	using TRawSofaTableByDistances = std::vector<TDistanceBucketRawSofa>;
		
	/**
	 * @brief Type definition for the distance table, this is used for rendering.
	 */
	using TDistanceTable = std::vector<TDistanceBucket>;	
}
#endif