#include "SlidingMinMax.hpp"

template <typename T>
SlidingMinMax<T>::SlidingMinMax(Mode mode, size_t L, T P)
: m_mode(mode)
, m_L(L)
, m_P(P)
, m_N(0)
, m_win_value(0)
, m_win_index(0)
{
	m_pP.resize(L);
	m_pP_last.resize(L);
	m_pU.resize(L);
	m_pU_last.resize(L);

	m_pP = 0;
	m_pP_last = 0;
	m_pU = T(0);
	m_pU_last = T(0);
	m_pU_last[1] = P;

	m_mode_value = 1.0;
	if (mode == Mode::Min)
	{
		m_mode_value = -1.0;
	}

}

template <typename T>
SlidingMinMax<T>::~SlidingMinMax()
{

}

template <typename T>
void SlidingMinMax<T>::process(T const &xin)
{
	T x = xin*m_mode_value;

	size_t m = 1;
	if (m_pP_last[m_N] == m_L)
	{
		m = 0;
		m_pU_last[m_N] = m_P;
	}

	size_t i = 0;
	while (x >= m_pU_last[i+1])
	{
		i++;
	}
	m_N = m_N - i + m;

	for (size_t j=1; j < m_N; j++)
	{
		m_pU[j+1] = m_pU_last[j+i];
		m_pP[j+1] = m_pP_last[j+i] + 1;
	}
	m_pU[m_N+1] = m_P;
	m_pU[1] = x;
	m_pP[1] = 1;

	i=0;
	while(m_pU[i] != m_P)
	{
		m_pU_last[i] = m_pU[i];
		m_pP_last[i] = m_pP[i];
		i++;
	}
	m_pU_last[i] = m_pU[i];
	m_pP_last[i] = m_pP[i];

	m_win_value = m_pU[m_N];
	m_win_index = m_pP[m_N];

}

