#include "TimeSliceCalibrator.h"

void TimeSliceCalibrator::initialise(const std::vector<size_t>& grid_sizes, const MFMBase* model)
{
	m_model = model;
	m_grid_sizes = grid_sizes;
}

void TimeSliceCalibrator::calibrate_at_T0(std::vector<std::unique_ptr<TimeSliceProcess>>& processes_at_T0)
{
	// won't do anything unless overidden in derived classes
}

void TimeSliceCalibrator::calibrate_at_T0(
	std::vector<std::unique_ptr<TimeSliceProcess>>& processes_at_T0,
	SliceProcessCorrelations const& T0_to_T1_increment)
{
	// by default, we don't use data from the increment. But this method can be overriden in derived classes if it is needed.
	calibrate_at_T0(processes_at_T0);
}

void TimeSliceCalibrator::calibrate(std::vector<std::unique_ptr<TimeSliceProcess>>& current_processes)
{
	// won't do anything unless overidden in derived classes
}

void TimeSliceCalibrator::calibrate(std::vector<std::unique_ptr<TimeSliceProcess>>& current_processes, SliceProcessCorrelations const& T0_to_T1_increment)
{
	// by default, we don't use data from the increment. But this method can be overriden in derived classes if it is needed.
	calibrate(current_processes);
}

void TimeSliceCalibrator::calibrate_next_at_T0(TimeSliceCalibrator& next_calibrator, std::vector<std::unique_ptr<TimeSliceProcess>>& current_processes, std::vector<std::unique_ptr<TimeSliceProcess>>& next_processes)
{
	// by default T0 behaves like other slices
	calibrate_next(next_calibrator, current_processes, next_processes);
}

void TimeSliceCalibrator::calibrate_next_at_T0(TimeSliceCalibrator& next_calibrator, std::vector<std::unique_ptr<TimeSliceProcess>>& current_processes, std::vector<std::unique_ptr<TimeSliceProcess>>& next_processes, SliceProcessCorrelations const& next_increment)
{
	// by default T0 behaves like other slices
	calibrate_next(next_calibrator, current_processes, next_processes, next_increment);
}

void TimeSliceCalibrator::calibrate_next(TimeSliceCalibrator& next_calibrator, std::vector<std::unique_ptr<TimeSliceProcess>>& current_processes, std::vector<std::unique_ptr<TimeSliceProcess>>& next_processes)
{
	// won't do anything unless overidden in derived classes
}

void TimeSliceCalibrator::calibrate_next(
	TimeSliceCalibrator& next_calibrator,
	std::vector<std::unique_ptr<TimeSliceProcess>>& current_processes, std::vector<std::unique_ptr<TimeSliceProcess>>& next_processes,
	SliceProcessCorrelations const & increment)
{
	// by default, we don't use data from the increments. But this method can be overriden in derived classes if it is needed.
	calibrate_next(next_calibrator, current_processes, next_processes);
}

void TimeSliceCalibrator::calculate_next_spot_values(std::vector<std::unique_ptr<TimeSliceProcess>>& next_processes)
{
	for (auto& process : next_processes)
		process->calculate_spot();
}

double TimeSliceCalibrator::roll_back(std::vector<double> const& spread) const
{
	throw std::runtime_error("Roll back was called from a calibrator but there is no roll back function implemented");
	// This method must be overriden to work
	return std::numeric_limits<double>::quiet_NaN();
}
