/*
 * Copyright (c) 2015 Tricoire Sebastien 3dsman@free.fr
 *
 * This software is provided 'as-is', without any express or implied
 * warranty.  In no event will the authors be held liable for any damages
 * arising from the use of this software.
 *
 * Permission is granted to anyone to use this software for any purpose,
 * including commercial applications, and to alter it and redistribute it
 * freely, subject to the following restrictions:
 *
 * 1. The origin of this software must not be misrepresented; you must not
 * claim that you wrote the original software. If you use this software
 * in a product, an acknowledgment in the product documentation would be
 * appreciated but is not required.
 * 2. Altered source versions must be plainly marked as such, and must not be
 * misrepresented as being the original software.
 * 3. This notice may not be removed or altered from any source distribution.
 *
 */

#include "actions/OE_actionsCurves.h"
#include "OE_document.h"

///////// actionNewCurve ///////////////
/// \brief OE_actionNewCurve::OE_actionNewCurve
/// \param curve
///
OE_actionNewCurve::OE_actionNewCurve(OE_document* doc, OE_pointcurve* curve) : OE_actions(doc)
{
	if (document)
	{
		actionCurve = curve;
		document->addCurve(curve);
	}
}

OE_actionNewCurve::~OE_actionNewCurve()
{
}

void OE_actionNewCurve::undo()
{
	if (actionCurve && active)
	{
		document->removeCurve(actionCurve);
	}
	active = false;
}

void OE_actionNewCurve::redo()
{
	if (actionCurve && !active)
	{
		document->addCurve(actionCurve);
	}
	active = true;
}

///////// actionDelCurve ///////////////
/// \brief OE_actionDelCurve::OE_actionDelCurve
/// \param curve
///
OE_actionDelCurve::OE_actionDelCurve(OE_document* doc, OE_pointcurve* curve) : OE_actions(doc)
{
	if (document)
	{
		actionCurve = curve;
		document->removeCurve( curve);
	}
}

OE_actionDelCurve::~OE_actionDelCurve()
{
}

void OE_actionDelCurve::undo()
{
	if (actionCurve && active)
	{
		document->addCurve( actionCurve);
	}
	active = false;
}

void OE_actionDelCurve::redo()
{
	if (actionCurve && !active)
	{
		document->removeCurve(actionCurve);
	}
	active = true;
}

///////// actionNewCurve ///////////////
/// \brief OE_actionNewCurve::OE_actionNewCurve
/// \param curve
///
/*
OE_actionNewSubCurve::OE_actionNewSubCurve(OE_curve* curve,float curveStart, float curveEnd, bool reverse)
{
	if (document)
	{
		actionCurve = new OE_subcurve(curve, curveStart, curveEnd, reverse);
		document->addCurve(actionCurve);
	}
}

OE_actionNewSubCurve::~OE_actionNewSubCurve()
{
	if (actionCurve && !active)
	{
		delete actionCurve;
	}
}

void OE_actionNewSubCurve::undo()
{
	if (actionCurve && active)
	{
		document->removeCurve(actionCurve);
	}
	active = false;
}

void OE_actionNewSubCurve::redo()
{
	if (actionCurve && !active)
	{
		document->addCurve(actionCurve);
	}
	active = true;
}
*/

///////// actionNewJoinCurve ///////////////
/// \brief OE_actionNewJoinCurve::OE_actionNewJoinCurve
/// \param curve1
/// \param curve2
///
/*
OE_actionNewJoinCurve::OE_actionNewJoinCurve(OE_subcurve* curve1, OE_subcurve* curve2)
{
	if (document)
	{
		actionCurve = new OE_joincurve(curve1, curve2);
		document->addCurve(actionCurve);
	}
}

OE_actionNewJoinCurve::~OE_actionNewJoinCurve()
{
	if (actionCurve && !active)
	{
		delete actionCurve;
	}
}

void OE_actionNewJoinCurve::undo()
{
	if (actionCurve && active)
	{
		document->removeCurve(actionCurve);
	}
	active = false;
}

void OE_actionNewJoinCurve::redo()
{
	if (actionCurve && !active)
	{
		document->addCurve( actionCurve);
	}
	active = true;
}
*/

OE_actionJoincurveAddSubCurve::OE_actionJoincurveAddSubCurve(OE_document* doc, OE_joincurve* joincurve, int index,
                                                             OE_curve* curve, float start, float end,
                                                             bool reverse) : OE_actions(doc)
{
	if (joincurve)
	{
		actionCurve = joincurve;
		id = index;
		subcurve = new OE_subcurve(curve, start, end, reverse);
		actionCurve->addCurve(subcurve, index);
	}
}

OE_actionJoincurveAddSubCurve::~OE_actionJoincurveAddSubCurve()
{
	if (actionCurve && subcurve && !active)
	{
		actionCurve->removeCurve(subcurve);
		delete subcurve;
	}
}

void OE_actionJoincurveAddSubCurve::undo()
{
	if (actionCurve && subcurve && active)
	{
		actionCurve->removeCurve(subcurve);
	}
	active = false;
}

void OE_actionJoincurveAddSubCurve::redo()
{
	if (actionCurve && subcurve && !active)
	{
		actionCurve->addCurve(subcurve, id);
	}
	active = true;
}

bool OE_actionJoincurveAddSubCurve::getDir()
{
	return subcurve ? subcurve->getReverse() : false;
}

void OE_actionJoincurveAddSubCurve::setEnd(float end)
{
	if (subcurve)
	{
		subcurve->setEnd(end);
	}
}

void OE_actionJoincurveAddSubCurve::setStart(float start)
{
	if (subcurve)
	{
		subcurve->setStart(start);
	}
}

void OE_actionJoincurveAddSubCurve::setDir(bool dir)
{
	if (subcurve)
	{
		subcurve->setReverse(dir);
	}
}

OE_actionMovePointCurve::OE_actionMovePointCurve(OE_document* doc, OE_pointcurve* curve, uint16_t idPoint, vector_2d offset) : OE_actions(doc)
{
	if (document && curve)
	{
		actionCurve = curve;
		if (actionCurve->getPoint(idPoint, oldCoord))
		{
			this->idPoint = idPoint;
			this->offset = offset;
			actionCurve->movePoint(idPoint, oldCoord + offset);
		}
	}
}

OE_actionMovePointCurve::~OE_actionMovePointCurve()
{
}

void OE_actionMovePointCurve::undo()
{
	if (actionCurve && active)
	{
		actionCurve->movePoint(idPoint, oldCoord);
	}
	active = false;
}

void OE_actionMovePointCurve::redo()
{
	if (actionCurve && !active)
	{
		actionCurve->movePoint(idPoint, oldCoord + offset);
	}
	active = true;
}

void OE_actionMovePointCurve::setMove(vector_2d offset)
{
	if (actionCurve)
	{
		this->offset = offset;
		if (active)
		{
			actionCurve->movePoint(idPoint, oldCoord + offset);
		}
	}
}



OE_actionSetCloseCurve::OE_actionSetCloseCurve(OE_document* doc, OE_curve* curve, bool closed) : OE_actions(doc)
{
	if (document && curve)
	{
		actionCurve = curve;
		this->closed = closed;
		this->oldClosed = actionCurve->getClosed();
		this->oldPts = actionCurve->getNpts();
		actionCurve->setClosed(closed);
	}
}

OE_actionSetCloseCurve::~OE_actionSetCloseCurve()
{
}

void OE_actionSetCloseCurve::undo()
{
	if (actionCurve && active)
	{
		if (!oldClosed && (oldPts < actionCurve->getNpts()))
		{
			actionCurve->pts.erase(actionCurve->pts.end()-3, actionCurve->pts.end());
		}
		actionCurve->setClosed(oldClosed);
	}
	active = false;
}

void OE_actionSetCloseCurve::redo()
{
	if (actionCurve && !active)
	{
		actionCurve->setClosed(closed);
	}
	active = true;
}

OE_actionSetSubcurvePos::OE_actionSetSubcurvePos(OE_document* doc, OE_subcurve* curve, bool start, double pos) : OE_actions(doc)
{
	if (document&&curve)
	{
		actionCurve = curve;
		this->start = start;
		this->pos = pos;
		if (start)
		{
			oldPos = actionCurve->getStart();
			actionCurve->setStart(pos);
		}
		else
		{
			oldPos = actionCurve->getEnd();
			actionCurve->setEnd(pos);
		}
	}
}

OE_actionSetSubcurvePos::~OE_actionSetSubcurvePos()
{
}

void OE_actionSetSubcurvePos::undo()
{
	if (active)
	{
		if (start)
		{
			actionCurve->setStart(oldPos);
		}
		else
		{
			actionCurve->setEnd(oldPos);
		}

		if (invert)
		{
			actionCurve->setReverse(!actionCurve->getReverse());
		}
		active = false;
	}
}

void OE_actionSetSubcurvePos::redo()
{
	if (!active)
	{
		if (start)
		{
			actionCurve->setStart(pos);
		}
		else
		{
			actionCurve->setEnd(pos);
		}

		if (invert)
		{
			actionCurve->setReverse(!actionCurve->getReverse());
		}
		active = true;
	}
}

void OE_actionSetSubcurvePos::setPos(double pos)
{
	this->pos = pos;
	if (active)
	{
		if (start)
		{
			actionCurve->setStart(pos);
		}
		else
		{
			actionCurve->setEnd(pos);
		}
	}
}

void OE_actionSetSubcurvePos::setInvertDir(bool invert)
{
	if (active)
	{
		if (this->invert != invert)
		{
			actionCurve->setReverse(!actionCurve->getReverse());
		}
	}
	this->invert = invert;
}

bool OE_actionSetSubcurvePos::getInvertDir()
{
	return invert;
}

