#include "speechdetectionandseparation.h"

#include "analysistransform.h"
#include "synthesistransform.h"
#include "soundfielddescription.h"
#include "packager.h"
#include "AudioFile.h"
#include "noisecancellation.h"


#include <fstream>
#include <iostream>

int main()
{


		char audioscenegeometry[] = R"(
		{
				"$schema": "http://json-schema.org/draft-07/schema#",
				"title" : "Audio Scene Geometry",
				"BlockIndex": 1,
				"BlockStart" : 1659533438878,
				"BlockEnd" : 1659533438898,
				"SpeechCount" : 1,
				"SourceDetectionMask" : [1,1,1],
				"SpeechList": [
								{"SpeechID" :  "09859d16-3c73-4bb0-9c74-91b451e34925", "ChannelID" : 0.0, "AzimuthDirection" : 0.35836, "ElevationDirection" : 0.0, "DistanceFlag" : 0.93358, "Distance" : 0.0}
							  ]
		}

		)";


		char microphonearraygeometry[] = R"(
		{
			"$schema": "http://json-schema.org/draft-07/schema#",
			"title": "Microphone Array Geometry",
			"MicrophoneArrayType": 0,
			"MicrophoneArrayScat": 0,
			"MicrophoneArrayFilterURI": "filter.file",
			"SamplingRate": 4,
			"SampleType": 2,
			"BlockSize": 5,
			"NumberofMicrophones": 32,
			"MicrophoneList" : [
					{"xCoord" :  0.93358,"yCoord" : 0.0,"zCoord" : 0.35836,"directivity" : 1.0,"micxLookCoord" : 0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : 0.35836},
					{"xCoord" :  0.84804,"yCoord" : 0.52991,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : 0.84804,"micyLookCoord" : 0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  0.93358,"yCoord" : 0.0,"zCoord" : -0.35836,"directivity" : 1.0,"micxLookCoord" : 0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : -0.35836},
					{"xCoord" :  0.84804,"yCoord" : -0.52991,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : 0.84804,"micyLookCoord" : -0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  0.52991,"yCoord" : 0.0,"zCoord" : 0.84804,"directivity" : 1.0,"micxLookCoord" : 0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : 0.84804},
					{"xCoord" :  0.57922,"yCoord" : 0.57922,"zCoord" : 0.57357,"directivity" : 1.0,"micxLookCoord" : 0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  0.35836,"yCoord" : 0.93358,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : 0.35836,"micyLookCoord" : 0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  0.57922,"yCoord" : 0.57922,"zCoord" : -0.57357,"directivity" : 1.0,"micxLookCoord" : 0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  0.52991,"yCoord" : 0.0,"zCoord" : -0.84804,"directivity" : 1.0,"micxLookCoord" : 0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : -0.84804},
					{"xCoord" :  0.57922,"yCoord" : -0.57922,"zCoord" : -0.57357,"directivity" : 1.0,"micxLookCoord" : 0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  0.35836,"yCoord" : -0.93358,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : 0.35836,"micyLookCoord" : -0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  0.57922,"yCoord" : -0.57922,"zCoord" : 0.57357,"directivity" : 1.0,"micxLookCoord" : 0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  -0.00625,"yCoord" : 0.35831,"zCoord" : 0.93358,"directivity" : 1.0,"micxLookCoord" : -0.00625,"micyLookCoord" : 0.35831,"miczLookCoord" : 0.93358},
					{"xCoord" :  0.0,"yCoord" : 0.84804,"zCoord" : 0.52991,"directivity" : 1.0,"micxLookCoord" : 0.0,"micyLookCoord" : 0.84804,"miczLookCoord" : 0.52991},
					{"xCoord" :  0.0,"yCoord" : 0.85716,"zCoord" : -0.51503,"directivity" : 1.0,"micxLookCoord" : 0.0,"micyLookCoord" :  0.85716,"miczLookCoord" : -0.51503},
					{"xCoord" :  0.006254,"yCoord" : 0.35831,"zCoord" : -0.93358,"directivity" : 1.0,"micxLookCoord" : 0.006254,"micyLookCoord" : 0.35831,"miczLookCoord" : -0.93358},
					{"xCoord" :  -0.93358,"yCoord" : 0.0,"zCoord" : 0.35836,"directivity" : 1.0,"micxLookCoord" : -0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : 0.35836},
					{"xCoord" :  -0.84804,"yCoord" : -0.52991,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : -0.84804,"micyLookCoord" : -0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.93358,"yCoord" : 0.0,"zCoord" : -0.35836,"directivity" : 1.0,"micxLookCoord" : -0.93358,"micyLookCoord" : 0.0,"miczLookCoord" : -0.35836},
					{"xCoord" :  -0.84804,"yCoord" : 0.52991,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : -0.84804,"micyLookCoord" : 0.52991,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.52991,"yCoord" : 0.0,"zCoord" : 0.84804,"directivity" : 1.0,"micxLookCoord" : -0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : 0.84804},
					{"xCoord" :  -0.57922,"yCoord" : -0.57922,"zCoord" : 0.57357,"directivity" : 1.0,"micxLookCoord" : -0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  -0.35836,"yCoord" : -0.93358,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : -0.35836,"micyLookCoord" : -0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.57922,"yCoord" : -0.57922,"zCoord" : -0.57357,"directivity" : 1.0,"micxLookCoord" : -0.57922,"micyLookCoord" : -0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  -0.52991,"yCoord" : 0.0,"zCoord" : -0.84804,"directivity" : 1.0,"micxLookCoord" : -0.52991,"micyLookCoord" : 0.0,"miczLookCoord" : -0.84804},
					{"xCoord" :  -0.57922,"yCoord" : 0.57922,"zCoord" : -0.57357,"directivity" : 1.0,"micxLookCoord" : -0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : -0.57357},
					{"xCoord" :  -0.35836,"yCoord" : 0.93358,"zCoord" : 0.0,"directivity" : 1.0,"micxLookCoord" : -0.35836,"micyLookCoord" : 0.93358,"miczLookCoord" : 0.0},
					{"xCoord" :  -0.57922,"yCoord" : 0.57922,"zCoord" : 0.57357,"directivity" : 1.0,"micxLookCoord" : -0.57922,"micyLookCoord" : 0.57922,"miczLookCoord" : 0.57357},
					{"xCoord" :  -0.00625,"yCoord" : -0.35831,"zCoord" : 0.93358,"directivity" : 1.0,"micxLookCoord" : -0.00625,"micyLookCoord" : -0.35831,"miczLookCoord" : 0.93358},
					{"xCoord" :  0.0,"yCoord" : -0.84804,"zCoord" : 0.52991,"directivity" : 1.0,"micxLookCoord" : 0.0,"micyLookCoord" : -0.84804,"miczLookCoord" : 0.52991},
					{"xCoord" :  0.0,"yCoord" : -0.84804,"zCoord" : -0.52991,"directivity" : 1.0,"micxLookCoord" : 0.0,"micyLookCoord" : -0.84804,"miczLookCoord" : -0.52991},
					{"xCoord" :  0.00625,"yCoord" : -0.35831,"zCoord" : -0.93358,"directivity" : 1.0,"micxLookCoord" : 0.00625,"micyLookCoord" : -0.35831,"miczLookCoord" : -0.93358}
				],
			 "MicrophoneArrayLookCoord" : {"xLookCoord" : 0.0, "yLookCoord" : 0.0, "zLookCoord" : 0.0}
		}
     )";

		int Nofsamples;

		int nofmics = 32;
		// Read the microphone array audio files for test
		vector<AudioFile<float>> vec_audio = vector<AudioFile<float>>();
		for (int ml = 0; ml < nofmics; ml++)
		{
			AudioFile<float> a;

			//const std::string inputFilePath = std::string("C:/Users/ihtar/Desktop/Nemeth/Nemeth") + std::to_string(ml + 1) + ".wav";
		   //const std::string inputFilePath = std::string("C:/Users/ihtar/Desktop/mhacoustics_studio/ShowcaseShowdown_") + std::to_string(ml+1) + ".wav";

			const std::string inputFilePath = std::string("C:/Users/ihtar/Desktop/Speech_folder/20220312-101950/AC_0/speech") + std::to_string(ml) + ".wav";
			bool loadedOK = a.load(inputFilePath);
			Nofsamples = 307200; // a.getNumSamplesPerChannel();
			if (loadedOK)
				vec_audio.push_back(a);
		}

		int windowsize = 2048;
		int blocksize = 1;
		int total =2048; // windowsize* blocksize;


		double* signal = (double*)calloc(total * nofmics, sizeof(double));
		double* signal_out = (double*)calloc(total * nofmics, sizeof(double));
		float* realpart = (float*)calloc(nofmics * (windowsize/2) * blocksize, sizeof(float));
		float* imagpart = (float*)calloc(nofmics * (windowsize/2) * blocksize, sizeof(float));

		analysistransform* m_fft = new analysistransform(windowsize, total, windowsize/2, nofmics);

		synthesistransform* m_ifft = new synthesistransform(windowsize, (windowsize /2) * blocksize, windowsize / 2, nofmics);

		//soundfielddescription sfd = soundfielddescription(microphonearraygeometry);
		speechdetectionandseparation* sds =new speechdetectionandseparation(microphonearraygeometry, blocksize);
		noisecancellation* nc = new noisecancellation(windowsize, blocksize);

		sds->initialization(windowsize);
		int nofsource = 2;
		AudioFile<float>::AudioBuffer buffer;
		buffer.resize(nofsource);

		for (int klo = 0; klo < nofsource; klo++)
		{
			buffer[klo].resize(Nofsamples);

		}
		int overlap = 0;
		bool checkit = false;
		for (int id = 0; id < Nofsamples; id += (total))
		{

			for (int idk = 0; idk < total; idk++)
			{
				if ((id + idk) < Nofsamples)
				{
					for (int mic_id = 0; mic_id < nofmics; mic_id++)
					{

						*(signal + idk * nofmics + mic_id) =  vec_audio[mic_id].samples[0][(int)(id + idk)]; // 0.5 * sin(2.0 * 3.14 * 0.0625 * (float)(id + idk)); //
					}
				}
				else
				{
					for (int mic_id = 0; mic_id < nofmics; mic_id++)
					{
						*(signal + idk * nofmics + mic_id) = 0.0;
					}
				} 
				
			}

			

			std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
			m_fft->FFT(signal, realpart, imagpart);

	//m_ifft->SetSourceSize(nofsource);
	//m_ifft->IFFT(signal_out, realpart, imagpart);
		
			// Detect the number of sources via RENT
			nofsource = sds->RENTComputation(realpart, imagpart);
			if (nofsource > 0)
			{
				// Speech separation results 
				complex_num num_res = sds->SpeechSeparation();
				complex_num multip_SRF = sds->Return_BlockSRF();
				// Audio Scene Description
				nc->getwienermatrices(sds->audioscenegeometry_out());
				// Speech Separation Results and spherical harmonics will be input for noise cancellation
				nc->Operate_NoiseCancellation(multip_SRF.real, multip_SRF.imag, num_res.real, num_res.imag);
				// Set the number of sources after speech detection and separation
				m_ifft->SetSourceSize(nofsource);
				// Inverse FFT is applied for the separated sources
				m_ifft->IFFT(signal_out, num_res.real, num_res.imag);
			}
			
		
				//float maxval = 0.0;
			float averaging = 0.0;
			float preaveraging = 0.0;
			for (int channel = 0; channel < nofsource; channel++)
			{
				int counter = overlap* nofsource;
				for (int ijk = id; ijk < id + total; ijk++)
				{
					if (ijk >= Nofsamples)
						break;
					//if(channel == 0)
					//	printf("%f,", signal_out[counter + channel]);
					/*if (ijk > id + total - 10)
						averaging += (float)signal_out[counter + channel];
					*/
					//if (ijk == id + 1024 || ijk == id + 3071 || ijk == id)
						buffer[channel][ijk] = (double)signal_out[counter + channel]; 
					//else
					//	buffer[channel][ijk] = 0.0;
					counter += nofsource;
				}
			}

			//preaveraging = averaging / 10.0;
			//if(!checkit)
			id = id - overlap;

			//checkit = true;
			//signal_out = (double*)calloc(total * nofmics, sizeof(double));
			std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
			std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds> (end - begin).count() << "Samples :" << id << "Total:" << Nofsamples << std::endl;
		}

		AudioFile<float> a;
		a.setBitDepth(32);
		a.setSampleRate(48000);
		a.setAudioBuffer(buffer);
		a.save(std::string("seperated.wav"), AudioFileFormat::Wave);

		int msgsize = 0;
		packager m_packager;
		//unsigned char* result = m_packager.createdata(audioscenegeometry, microphonearraygeometry, signal_out, &msgsize);

	return 0;
}
