ECGController::ECGController (void) :
  ecg_baseline_module(new BaselineRemoval()),
  rpeaks_module(new RPeaksDetector()),
  hrv1_module(new HRV1Analyzer())
{
  TRI_LOG_STR("ECGController created, 20:51 17-12-2012");
  //TODO: create modules objects
}
void ECGController::setWavesNotRun()
{
  TRI_LOG_STR(__FUNCTION__);
  waves_module->run_ = false;
  setQRSClassNotRun();
  setSTIntervalNotRun();
  setTwaveAltNotRun();
  setHRTNotRun();
  LOG_END
}
void ECGController::setRPeaksNotRun()
{
  TRI_LOG_STR(__FUNCTION__);
  rpeaks_module->run_ = false;
  setHRTNotRun();
  setWavesNotRun();
  setHRV1NotRun();
  setHRV2NotRun();
  setHRVDFANotRun();
  LOG_END
}
void ECGController::runHRVDFA ()
{
  TRI_LOG_STR(__FUNCTION__);
  if (!rpeaks_module->run_)
  {
    runRPeaks();
  }
  hrv_dfa_module->runModule(r_peaks_data, hrv_dfa_data);
  hrv_dfa_module->run_ = true;
  LOG_END
}
void ECGController::runRPeaks ()
{
  TRI_LOG_STR(__FUNCTION__);
  if (!ecg_baseline_module->run_)
  {
    runECGBaseline();
  }
  rpeaks_module->runModule(filtered_signal, ecg_info, r_peaks_data);
  rpeaks_module->run_ = true;
  LOG_END
}
void ECGController::setECGBaselineNotRun()
{
  TRI_LOG_STR(__FUNCTION__);
  ecg_baseline_module->run_ = false;
  setRPeaksNotRun();
  setQRSClassNotRun();
  setSTIntervalNotRun();
  setTwaveAltNotRun();
  setHRTNotRun();
  setWavesNotRun();
  LOG_END
}
bool ECGController::readFile(std::string filename)
{
  TRI_LOG_STR(__FUNCTION__);
  //check filename to be correct with WFDB
  int pos;
  if ((pos = filename.find('.')) != std::string::npos)
  {
    filename = filename.substr(0, pos);
  }

  int nr_samples;

  size_t i;
  WFDB_Sample v[2];
  WFDB_Siginfo s[2];
  if (isigopen(const_cast<char*> (filename.c_str()), s, 2) < 2)
  {
    TRI_LOG_STR("File");
    TRI_LOG(filename);
    TRI_LOG_STR("Not loaded");
    LOG_END
    return false;
  }
void ECGController::runTwaveAlt ()
{
  TRI_LOG_STR(__FUNCTION__);
  if (!ecg_baseline_module->run_)
  {
    runECGBaseline();
  }
  if (!waves_module->run_)
  {
    runWaves();
  }
  t_wave_alt_module->runModule(waves_data, filtered_signal, ecg_info, twave_data);
  t_wave_alt_module->run_ = true;
  LOG_END
}
void ECGController::runSTInterval ()
{
  TRI_LOG_STR(__FUNCTION__);
  if (!ecg_baseline_module->run_)
  {
    runECGBaseline();
  }
  if (!waves_module->run_)
  {
    runWaves();
  }
  st_interval_module->runModule(waves_data, filtered_signal, ecg_info, st_data);
  st_interval_module->run_ = true;
  LOG_END
}
void ECGController::runQRSClass ()
{
  TRI_LOG_STR(__FUNCTION__);
  if (!ecg_baseline_module->run_)
  {
    runECGBaseline();
  }
  if (!waves_module->run_)
  {
    runWaves();
  }
  qrs_class_module->runModule(waves_data, filtered_signal, ecg_info, classes_data);
  qrs_class_module->run_ = true;
  LOG_END
}
b2Fixture* BodyWrapper::LookUpFixture( const std::string& fixtureName ) const
{
    FixtureMap::const_iterator iter = _fixtureMap.find( fixtureName );
    if( iter != _fixtureMap.end() )
    {
        return iter->second.fixture;
    }
    else
    {
		TRI_LOG_STR("Unable to find fixture.");
		TRI_LOG(fixtureName);
    }

    return nullptr;
}
ECGController::~ECGController (void)
{
  TRI_LOG_STR("ECGController destroyed");
}
void ECGController::setHRTNotRun()
{
  TRI_LOG_STR(__FUNCTION__);
  hrt_module->run_ = false;
  LOG_END
}
void ECGController::setTwaveAltNotRun()
{
  TRI_LOG_STR(__FUNCTION__);
  t_wave_alt_module->run_ = false;
  LOG_END
}
void ECGController::setSTIntervalNotRun()
{
  TRI_LOG_STR(__FUNCTION__);
  st_interval_module->run_ = false;
  LOG_END
}
void RPeaksDetector::setParams(ParametersTypes &parameterTypes)
{
	TRI_LOG_STR(__FUNCTION__);
	if(parameterTypes.find("detection_method") != parameterTypes.end())
	{
		int method = (int)parameterTypes["detection_method"];
		if(method == 0)
		{
			this->detectionMethod = HILBERT;
		}
		else if(method == 1)
		{
            this->detectionMethod = PAN_TOMPKINS;
		}
		else
		{
			#ifdef DEBUG
				qDebug() << "Unknown detection method";
			#endif
			TRI_LOG_STR("Unknown detection method.");
			throw new RPeaksDetectionException("Unknown detection method.");
		}
	}
	else {
		#ifdef DEBUG
			qDebug() << "Parameter: detection method not found";
		#endif
		TRI_LOG_STR("Parameter: detection method not found");
		throw new RPeaksDetectionException("Parameter: detection method not found");
	}
	
	if(parameterTypes.find("window_size") != parameterTypes.end())
	{
		this->panTompkinsMovinghWindowLenght = (int)parameterTypes["window_size"];
	}
	else {
		#ifdef DEBUG
			qDebug() << "Window size not found, use automatic calculated value";
		#endif
	}

	if(parameterTypes.find("threshold_size") != parameterTypes.end())
	{
		panTompkinsThershold = parameterTypes["threshold_size"];
	}
	else {
		#ifdef DEBUG
			qDebug() << "Thersold size not found, use automatic calculated value";
		#endif
	}
	this->customParameters = true;

	#ifdef DEBUG
			cout << "Input parameters for R peaks module:" << endl;
			if(this->detectionMethod == PAN_TOMPKINS)
			{
				qDebug()  << "Detection method: PanTompkins" << endl
						  << "Moving window size: " << this->panTompkinsMovinghWindowLenght << endl
						  << "Thersold size: " << panTompkinsThershold;
			} 
			else if (this->detectionMethod == HILBERT)
			{
				qDebug() << "Detection method: Hilbert";
			}
			else
			{
				qDebug() << "Unknown detection method";
			}
	#endif
	LOG_END;
}
bool RPeaksDetector::panTompkinsRPeaksDetection(ECGSignalChannel *signal)
{
	TRI_LOG_STR(__FUNCTION__);
	ECGSignalChannel sig;
	sig = *signal;
	int sigSize = 0;
	if(sig->signal->size < 1)
	{
		#ifdef DEBUG
			qDebug() << "Input signal size is 0";
		#endif
		TRI_LOG_STR("Input signal size is 0");
		return false;
	}
	else
	{
		sigSize = sig->signal->size;
		#ifdef DEBUG_SIGNAL
			qDebug() << "Input signal";	
			for(int i = 0; i < sigSize; i++)
			{
				double inputValue = gsl_vector_get (sig->signal, i);	
				qDebug() << inputValue;	
			}
		#endif
	}

	//Convolution [-0.125 -0.25 0.25 0.125] (Here we lose 4 signal samples)	
	#ifdef DEBUG
		qDebug() << "Convolution [-0.125 -0.25 0.25 0.125]" << endl << "Orginal signal size: " << sigSize;
	#endif
	int newSigSize = 0;
	ECGSignalChannel diffSig;
	diffSig = ECGSignalChannel(new WrappedVector);
	diffSig->signal = gsl_vector_alloc(sigSize);
	double filter[] = {-0.125, -0.25, 0.25, 0.125};
	int filterSize = 4;
	for(int i = 0; i < sigSize - filterSize; i++)
	{
		double tmpSum = 0;
		for(int j = 0; j < filterSize; j++)
		{
			double inputValue = gsl_vector_get (sig->signal, i + j);			
			tmpSum += inputValue * filter[j];
			#ifdef DEBUG_SIGNAL_DETAILS
				qDebug() << "Signal: " << inputValue << " Filter: " << filter[j] << " Sum: " << tmpSum;
			#endif
		}
		#ifdef DEBUG_SIGNAL
			qDebug() << "Final val: " << tmpSum << " at index: " << i;
		#endif
		gsl_vector_set(diffSig->signal, i, tmpSum);
		newSigSize++;
	}
	
	//Exponentiation
	sigSize = newSigSize;
	#ifdef DEBUG
		qDebug() << "Exponentiation ^2" << endl << "Signal size after convolution: " << sigSize;
	#endif
	ECGSignalChannel powSig;
	powSig = ECGSignalChannel(new WrappedVector);
	powSig->signal = gsl_vector_alloc(sigSize);
	for(int i = 0; i < sigSize; i++)
	{
		double inputValue = gsl_vector_get (diffSig->signal, i);			
		double powVal = pow(inputValue, 2);
		gsl_vector_set(powSig->signal, i, powVal);
		#ifdef DEBUG_SIGNAL
				qDebug() << " Pow: "<< powVal << " at index: " << i;
		#endif
	}

	//Calculae moving window lenght or use custom value
	// N=30 for f=200Hz - from literature
	// N=24 for f=360Hz - from literature and tests
	// Linear function for calculating window lenght
	// wl = -0.0375 * fs + 37.5
	if(panTompkinsMovinghWindowLenght == 0)
	{
		panTompkinsMovinghWindowLenght = -0.0375 * signalFrequency + 37.5;
	}

	//Moving window integration (Here we lose "movinghWindowLenght" signal samples)
	#ifdef DEBUG
		qDebug() << "Moving window integration" << endl << "Window size: " << panTompkinsMovinghWindowLenght << endl
				  << "Signal size after exponentiation: " << sigSize;
	#endif
	ECGSignalChannel integrSig;
	integrSig = ECGSignalChannel(new WrappedVector);
	integrSig->signal = gsl_vector_alloc(sigSize);
	newSigSize = 0;
	int movinghWindowLenght = panTompkinsMovinghWindowLenght;
	double tmpSum = 0;

	for(int i = movinghWindowLenght; i < sigSize; i++)
	{
		for(int j = movinghWindowLenght - 1; j >= 0 ; j--)
		{
			double inputValue = gsl_vector_get (powSig->signal, i - j);			
			tmpSum += inputValue;
			#ifdef DEBUG_SIGNAL_DETAILS
				qDebug() << "Signal: " << inputValue << " Sum: " << tmpSum;
			#endif
		}
		int index = i - movinghWindowLenght;
		// TODO Why this is not working? (To small values and all are save as zero)
		//double mwico = (1/movinghWindowLenght) * tmpSum;
		double mwico =  tmpSum;
		#ifdef DEBUG_SIGNAL
			qDebug() << "Final val: " << mwico << " at index: " << index;
		#endif
		gsl_vector_set(integrSig->signal, index, mwico);
		tmpSum = 0;
		newSigSize++;
	}

	//Calculating detection threshold
	//TODO (Not important now) Try to find another way to calcutale threshold position, maybe dynamic threshold?
	sigSize = newSigSize;
	#ifdef DEBUG
	qDebug() << "Calculating detection threshold" << endl << "After moving window integration signal size: " << sigSize;
	#endif
	double sigMaxVal = 0;
	double meanVal = 0;

	for(int i = 0; i < sigSize; i++)
	{
		double inputValue = gsl_vector_get (integrSig->signal, i);					
		if(inputValue > sigMaxVal)
		{
			sigMaxVal = inputValue;
			#ifdef DEBUG_SIGNAL
				qDebug() << "New max signal value: " << inputValue;
			#endif
		}
		meanVal += inputValue;
	}
	meanVal = meanVal / sigSize;

	#ifdef DEBUG
		qDebug() << "Final max value for channel one: " << sigMaxVal << endl
	         << "Final mean value: " << meanVal << endl;

	#endif

	// Select automatic or manual thersold
	double threshold = 0;
	if( this->panTompkinsThershold == 0)
	{
		threshold = meanVal + (sigMaxVal * 0.04);
	}
	else
	{
		threshold = this->panTompkinsThershold;
	}

	//Looking for points over thersold
	#ifdef DEBUG
		qDebug() << "Current thresold value: " << threshold << endl << "Looking for points over thersold";
	#endif
	ECGSignalChannel overThersold;
	overThersold = ECGSignalChannel(new WrappedVector);
	overThersold->signal = gsl_vector_alloc(sigSize);
	for(int i = 0; i < sigSize; i++)
	{
		double inputValue = gsl_vector_get (integrSig->signal, i);			
		if(inputValue > threshold * sigMaxVal)
		{
			gsl_vector_set(overThersold->signal, i, 1);
			#ifdef DEBUG_SIGNAL
				qDebug() << "Value over thersold at index: " << i;
			#endif
		}
		else
		{
			gsl_vector_set(overThersold->signal, i, 0);
		}
	}
	#ifdef DEBUG_SIGNAL
		qDebug() << "Signal with points over thersold";
		for(int i = 0; i < sigSize; i++)
		{
			qDebug() << gsl_vector_get(overThersold->signal, i);
		}
	#endif
	#ifdef DEBUG
		qDebug() << "Detect begin and end of QRS complex";
	#endif
	ECGSignalChannel leftPoints;
	ECGSignalChannel tmpRightPoints;
	leftPoints = ECGSignalChannel(new WrappedVector);
	tmpRightPoints = ECGSignalChannel(new WrappedVector);
	leftPoints->signal = gsl_vector_alloc(sigSize);
	tmpRightPoints->signal = gsl_vector_alloc(sigSize);
	int leftPointsCount = 0;
	int rightPointsCount = 0;

	gsl_vector* copiedSig = gsl_vector_calloc(sigSize);
	gsl_vector_memcpy(copiedSig, overThersold->signal);

	// Boundary values
	if(gsl_vector_get (copiedSig, 0) == 1)
	{
		gsl_vector_set(leftPoints->signal, leftPointsCount, 0);
		leftPointsCount++;
		#ifdef DEBUG_SIGNAL
			qDebug() << "QRS complex left point at index: " << 0;
		#endif
	}
	
	if(gsl_vector_get (copiedSig, sigSize - 1) == 1)
	{
		gsl_vector_set(tmpRightPoints->signal, rightPointsCount, sigSize - 1);
		rightPointsCount++;
		#ifdef DEBUG_SIGNAL
			qDebug() << "QRS complex right point at index: " << sigSize - 1;
		#endif
	}

	// Left points of QRS complex
	for(int i = 0; i < sigSize - 1; i++)
	{
		double inputValue = gsl_vector_get (copiedSig, i);
		double inputValueIndexPlus = gsl_vector_get (copiedSig, i + 1);
		if((inputValueIndexPlus - inputValue) == 1)
		{
			gsl_vector_set(leftPoints->signal, leftPointsCount, i);
			leftPointsCount++;
			#ifdef DEBUG_SIGNAL
				qDebug() << "QRS complex left point at index: " << i;
			#endif
		}
	}

	// Rights points of QRS complex
	for(int i = sigSize - 1; i > 0; i--)
	{
		double reversedInput = gsl_vector_get(copiedSig, i);
		double reversedInputIndexMinus = gsl_vector_get (copiedSig, i - 1);
		if((reversedInputIndexMinus - reversedInput) == 1)
		{
			gsl_vector_set(tmpRightPoints->signal, rightPointsCount, i);
			rightPointsCount++;
			#ifdef DEBUG_SIGNAL
				qDebug() << "QRS complex right at index: " << i;
			#endif
		}
	}

	#ifdef DEBUG_SIGNAL
		cout << "Vector with left points:" << endl;
		for(int i = 0; i < leftPointsCount; i++)
		{
			qDebug() << gsl_vector_get(leftPoints->signal, i);
		}
		qDebug() << endl << "Vector with right points:";
		for(int i = 0; i < rightPointsCount; i++)
		{
			qDebug() << gsl_vector_get(tmpRightPoints->signal, i);
		}
		cout << endl;
	#endif
	// Invert vector with rightPoints
	ECGSignalChannel rightPoints;
	rightPoints = ECGSignalChannel(new WrappedVector);
	rightPoints->signal = gsl_vector_alloc(sigSize);
	for(int i = 0; i < rightPointsCount; i++)
	{
		double tmp = gsl_vector_get(tmpRightPoints->signal, rightPointsCount - i - 1);
		gsl_vector_set(rightPoints->signal, i, tmp );
	}
	for(int i = 0; i < rightPointsCount; i++)
	{
		double tmp = gsl_vector_get(tmpRightPoints->signal, rightPointsCount - i - 1);
		gsl_vector_set(rightPoints->signal, i, tmp );
	}
	#ifdef DEBUG_SIGNAL
		qDebug() << "After vector invertion" << endl;
		qDebug() << "Vector with left points:" << endl;
		for(int i = 0; i < leftPointsCount; i++)
		{
			qDebug() << gsl_vector_get(leftPoints->signal, i);
		}
		qDebug() << endl << "Vector with right points:" << endl;
		for(int i = 0; i < rightPointsCount; i++)
		{
			qDebug() << gsl_vector_get(rightPoints->signal, i);
		}
	#endif
	#ifdef DEBUG
		qDebug() << "Number of left points: " << leftPointsCount << endl
			     << "Number of right points: " << rightPointsCount;
	#endif

	//Final R peaks detection
	#ifdef DEBUG
		qDebug() << "Final R peaks detection";
	#endif

	int partLength;
	IntSignal rs;
	int numberRs = 0;

	if(leftPointsCount > 0 )
	{
		rs = IntSignal(new WrappedVectorInt);
		rs->signal = gsl_vector_int_alloc(leftPointsCount);
		for(int i = 0; i < leftPointsCount; i++)
		{		
			partLength = gsl_vector_get (rightPoints->signal, i) - gsl_vector_get(leftPoints->signal, i);
			double tmpMax = 0;
			int tmpMaxIndex = 0;
			for(int j = 0; j < partLength; j++)
			{
				int sigIndex = gsl_vector_get (leftPoints->signal, i) + j;
				double sigVal = gsl_vector_get(sig->signal, sigIndex);
				if(sigVal > tmpMax)
				{
					tmpMax = sigVal;
					tmpMaxIndex = sigIndex;
				}

			}
			gsl_vector_int_set(rs->signal, i, tmpMaxIndex);
			numberRs++;
			#ifdef DEBUG_SIGNAL
				qDebug() << "R point at index: " << tmpMaxIndex 
					     << " signal value: " << gsl_vector_get(sig->signal, tmpMaxIndex);
			#endif
		}
		rsPositions->setRs(rs);
		#ifdef DEBUG
			qDebug() << "Number of detected R-peaks:" << numberRs;
		#endif
	}
	else
	{
		#ifdef DEBUG
			qDebug() << "R peaks not detected. Check input signal.";
		#endif
		TRI_LOG_STR("R peaks not detected. Check input signal.");
		return false;
	}
	gsl_vector_free(copiedSig);

	rsDetected = true;
	#ifdef DEBUG
		qDebug() << "Done";
	#endif
	LOG_END;
	return true;
}