/*
 * 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_actionsSelection.h"
#include "OE_document.h"

///////// actionSelectionAddCurves ///////////////
/// \brief OE_actionSelectionAddCurves::OE_actionSelectionAddCurves
/// \param curves
///
OE_actionSelectionAddCurves::OE_actionSelectionAddCurves(OE_document* doc, std::list<OE_pointcurve*> curves, bool replace) : OE_actions(doc)
{
	if (document)
	{
		actionCurves = document->selectedCurves;
		if (replace)
		{
			document->selectedCurves = curves;
		}
		else
		{
			document->selectedCurves.merge(curves);
			document->selectedCurves.sort();
			document->selectedCurves.unique();
		}
	}
}

OE_actionSelectionAddCurves::~OE_actionSelectionAddCurves()
{
}

void OE_actionSelectionAddCurves::undo()
{
	if (active)
	{
		document->selectedCurves = switchVal(document->selectedCurves, &actionCurves);
		active = false;
	}
}

void OE_actionSelectionAddCurves::redo()
{
	if (!active)
	{
		document->selectedCurves = switchVal(document->selectedCurves, &actionCurves);
		active = true;
	}
}

///////// actionSelectionRemoveCurves ///////////////
/// \brief OE_actionSelectionRemoveCurves::OE_actionSelectionRemoveCurves
/// \param curves
///
OE_actionSelectionRemoveCurves::OE_actionSelectionRemoveCurves(OE_document* doc, std::list<OE_pointcurve*> curves) : OE_actions(doc)
{
	if (document)
	{
		actionCurves = document->selectedCurves;
		for (std::list<OE_pointcurve*>::iterator it=curves.begin(); it!=curves.end(); ++it)
		{
			document->selectedCurves.remove(*it);
		}
	}
}

OE_actionSelectionRemoveCurves::~OE_actionSelectionRemoveCurves()
{
}

void OE_actionSelectionRemoveCurves::undo()
{
	if (active)
	{
		document->selectedCurves = switchVal(document->selectedCurves, &actionCurves);
		active = false;
	}
}

void OE_actionSelectionRemoveCurves::redo()
{
	if (!active)
	{
		document->selectedCurves = switchVal(document->selectedCurves, &actionCurves);
		active = true;
	}
}

///////// actionSelectionClearCurves ///////////////
/// \brief OE_actionSelectionClearCurves::OE_actionSelectionClearCurves
///
OE_actionSelectionClearCurves::OE_actionSelectionClearCurves(OE_document* doc) : OE_actions(doc)
{
	if (document)
	{
		actionCurves = document->selectedCurves;
		document->selectedCurves.clear();
	}
}

OE_actionSelectionClearCurves::~OE_actionSelectionClearCurves()
{
}

void OE_actionSelectionClearCurves::undo()
{
	if (active)
	{
		document->selectedCurves = actionCurves;
	}
	active = false;
}

void OE_actionSelectionClearCurves::redo()
{
	if (!active)
	{
		document->selectedCurves.clear();
	}
	active = true;
}

///////// actionSelectionAddStitches ///////////////
/// \brief OE_actionSelectionAddStitches::OE_actionSelectionAddStitches
/// \param stitches
///
OE_actionSelectionAddStitches::OE_actionSelectionAddStitches(OE_document* doc, std::list<OE_stitchs*> stitches, bool replace) : OE_actions(doc)
{
	if (document)
	{
		actionStitches = document->selectedStitchs;
		if (replace)
		{
			document->selectedStitchs = stitches;
		}
		else
		{
			document->selectedStitchs.merge(stitches);
			document->selectedStitchs.sort();
			document->selectedStitchs.unique();
		}
	}
}

OE_actionSelectionAddStitches::~OE_actionSelectionAddStitches()
{
}

void OE_actionSelectionAddStitches::undo()
{
	if (active)
	{
		document->selectedStitchs = switchVal(document->selectedStitchs, &actionStitches);
		active = false;
	}
}

void OE_actionSelectionAddStitches::redo()
{
	if (!active)
	{
		document->selectedStitchs = switchVal(document->selectedStitchs, &actionStitches);
		active = true;
	}
}

///////// actionSelectionRemoveStitches ///////////////
/// \brief OE_actionSelectionRemoveStitches::OE_actionSelectionRemoveStitches
/// \param stitches
///
OE_actionSelectionRemoveStitches::OE_actionSelectionRemoveStitches(OE_document* doc, std::list<OE_stitchs*> stitches) : OE_actions(doc)
{
	if (document)
	{
		actionStitches = document->selectedStitchs;
		for (std::list<OE_stitchs*>::iterator it=stitches.begin(); it!=stitches.end(); ++it)
		{
			document->selectedStitchs.remove(*it);
		}
	}
}

OE_actionSelectionRemoveStitches::~OE_actionSelectionRemoveStitches()
{
}

void OE_actionSelectionRemoveStitches::undo()
{
	if (active)
	{
		document->selectedStitchs = switchVal(document->selectedStitchs, &actionStitches);
		active = false;
	}
}

void OE_actionSelectionRemoveStitches::redo()
{
	if (!active)
	{
		document->selectedStitchs = switchVal(document->selectedStitchs, &actionStitches);
		active = true;
	}
}

///////// actionSelectionClearStitches ///////////////
/// \brief OE_actionSelectionClearStitches::OE_actionSelectionClearStitches
///
OE_actionSelectionClearStitches::OE_actionSelectionClearStitches(OE_document* doc) : OE_actions(doc)
{
	if (document)
	{
		actionStitches = document->selectedStitchs;
		document->selectedStitchs.clear();
	}
}

OE_actionSelectionClearStitches::~OE_actionSelectionClearStitches()
{
}

void OE_actionSelectionClearStitches::undo()
{
	if (active)
	{
		document->selectedStitchs = actionStitches;
	}
	active = false;
}

void OE_actionSelectionClearStitches::redo()
{
	if (!active)
	{
		document->selectedStitchs.clear();
	}
	active = true;
}

///////// OE_actionSelectionClear ///////////////
/// \brief OE_actionSelectionClear::OE_actionSelectionClear
///
OE_actionSelectionClear::OE_actionSelectionClear(OE_document* doc) : OE_actions(doc)
{
	if (document)
	{
		actionClearCurves = new OE_actionSelectionClearCurves(document);
		actionClearStitches = new OE_actionSelectionClearStitches(document);
	}
}

OE_actionSelectionClear::~OE_actionSelectionClear()
{
	if (!active)
	{
		if(actionClearCurves)
		{
			delete actionClearCurves;
		}
		if(actionClearStitches)
		{
			delete actionClearStitches;
		}
	}
}

void OE_actionSelectionClear::undo()
{
	if (!active)
	{
		return;
	}

	if (actionClearCurves)
	{
		actionClearCurves->undo();
	}
	if (actionClearStitches)
	{
		actionClearStitches->undo();
	}
	active = false;
}

void OE_actionSelectionClear::redo()
{
	if (active)
	{
		return;
	}

	if (actionClearCurves)
	{
		actionClearCurves->redo();
	}
	if (actionClearStitches)
	{
		actionClearStitches->redo();
	}
	active = true;
}

OE_actionMoveSelection::OE_actionMoveSelection(OE_document* doc, vector_2d offset) : OE_actions(doc)
{
	if (document)
	{
		this->offset = offset;
		for (auto curve : document->selectedCurves)
		{
			curve->move(offset);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->move(offset);
		}
	}
}

OE_actionMoveSelection::~OE_actionMoveSelection()
{
}

void OE_actionMoveSelection::undo()
{
	if (active)
	{
		for (auto curve : document->selectedCurves)
		{
			curve->move(-offset);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->move(-offset);
		}
	}
	active = false;
}

void OE_actionMoveSelection::redo()
{
	if (!active)
	{
		for (auto curve : document->selectedCurves)
		{
			curve->move(offset);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->move(offset);
		}
	}
	active = true;
}

void OE_actionMoveSelection::setMove(vector_2d offset)
{
	if (active)
	{
		for (auto curve : document->selectedCurves)
		{
			curve->move(offset-this->offset);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->move(offset-this->offset);
		}
	}
	this->offset = offset;
}


OE_actionScaleSelection::OE_actionScaleSelection(OE_document* doc, vector_2d ratio, vector_2d pos) : OE_actions(doc)
{
	if (document)
	{
		this->pos = pos;
		this->ratio = ratio;
		for (auto curve : document->selectedCurves)
		{
			curve->scale(ratio, pos);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->scale(ratio, pos);
		}
	}
}

OE_actionScaleSelection::~OE_actionScaleSelection()
{
}

void OE_actionScaleSelection::undo()
{
	if (active)
	{
		for (auto curve : document->selectedCurves)
		{
			curve->scale(vector_2d(1,1)/ratio, pos);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->scale(vector_2d(1,1)/ratio, pos);
		}
	}
	active = false;
}

void OE_actionScaleSelection::redo()
{
	if (!active)
	{
		for (auto curve : document->selectedCurves)
		{
			curve->scale(ratio, pos);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->scale(ratio, pos);
		}
	}
	active = true;
}

void OE_actionScaleSelection::setScale(vector_2d ratio)
{
	if (active)
	{
		for (auto curve : document->selectedCurves)
		{
			curve->scale(ratio/this->ratio, pos);
		}
		for (auto stitch : document->selectedStitchs)
		{
			stitch->scale(ratio/this->ratio, pos);
		}
	}
	this->ratio = ratio;
}

