/*
	Copyright (C) 2025 Mark Tyler

	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.

	This program is distributed in the hope that it will be useful,
	but WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
	GNU General Public License for more details.

	You should have received a copy of the GNU General Public License
	along with this program in the file COPYING.
*/

#include <mtdatawell_math.h>

#include "mtwasp.h"



double mtWasp::ShapeSpline::get_y ( double const x ) const
{
	size_t const tot = m_points.size();

	if ( x < MIN_X() )
	{
		if ( tot > 0 && m_points[0].x == MIN_X() )
		{
			return m_points[0].y;
		}
		else
		{
			return m_point_start.y;
		}
	}

	if ( x > MAX_X() )
	{
		if ( tot > 0 && m_points[0].x == MAX_X() )
		{
			return m_points[tot - 1].y;
		}
		else
		{
			return m_point_end.y;
		}
	}

	mtGin::Vertex const * a[2] = { &m_point_start, &m_point_end };

	for ( size_t i = 0; i < tot; i++ )
	{
		if ( x == m_points[i].x )
		{
			return m_points[i].y;
		}

		if ( x < m_points[i].x )
		{
			a[1] = &m_points[i];
			break;
		}

		a[0] = &m_points[i];
	}

	double const dx = a[1]->x - a[0]->x;	// Never 0 as per = checks above
	double const dxp = (x - a[0]->x) / dx;

	return (1.0 - dxp) * a[0]->y + dxp * a[1]->y;
}

void mtWasp::ShapeSpline::add_point (
	double		x,
	double		y
	)
{
	size_t const tot = m_points.size();

	if ( tot >= 10 )
	{
		return;
	}

	normalize_xy ( x, y );
	m_points.emplace_back ( x, y, 0.0 );

	// X must be monotonically increasing
	for ( size_t i = 0; i < tot; i++ )
	{
		if ( m_points[i].x > x )
		{
			m_points[i].x = x;
		}
	}
}

void mtWasp::ShapeSpline::set_point (
	int	const	index,
	double		x,
	double		y
	)
{
	normalize_xy ( x, y );

	size_t const sindex = (size_t)index;
	size_t const tot = m_points.size();

	if ( sindex < tot )
	{
		m_points[sindex].x = x;
		m_points[sindex].y = y;

		// X must be monotonically increasing
		for ( size_t i = 0; i < sindex; i++ )
		{
			if ( m_points[i].x > x )
			{
				m_points[i].x = x;
			}
		}

		for ( size_t i = sindex+1; i < tot; i++ )
		{
			if ( m_points[i].x < x )
			{
				m_points[i].x = x;
			}
		}
	}

	// Quietly ignore invalid argument
}

void mtWasp::ShapeSpline::insert_point (
	int	const	index,
	double		x,
	double		y
	)
{
	normalize_xy ( x, y );

	size_t const tot = (size_t)index;

	if ( tot < m_points.size() )
	{
		m_points.emplace ( m_points.begin() + index, x, y, 0.0 );
	}

	// Quietly ignore invalid argument
}

void mtWasp::ShapeSpline::delete_point ( int const index )
{
	size_t const tot = (size_t)index;

	if ( tot < m_points.size() )
	{
		m_points.erase ( m_points.begin() + index );
	}

	// Quietly ignore invalid argument
}

