/*
* This file is part of project OpenEmbroidery. It's copyrighted by
* the contributors recorded in the version control history of the file.
* Original project location https://code.electrolab.fr/openEmbroidery/openEmbroidery_software
*
* SPDX-License-Identifier: CECILL-2.1
* License-Filename: Licence_CeCILL_V2.1-en.txt
*/

#include "stitchs/OE_linkstitch.h"
#include "curves/OE_curve.h"
#include "Archive.h"
#include <iostream>

float OE_linkstitch::defaultLinkMaxlen = 5.0f;

OE_linkstitch::OE_linkstitch(OE_stitchs* stitchStart, OE_stitchs* stitchEnd)
{
	this->stitchStart = stitchStart;
	if (stitchStart)
	{
		stitchStart->addDependency(this);
	}
	this->stitchEnd = stitchEnd;
	if (stitchEnd)
	{
		stitchEnd->addDependency(this);
	}
	maxLen = defaultLinkMaxlen;
	thread = stitchStart ? stitchStart->getThread() : nullptr;

	setNeedRefresh();
	//refresh();
}

OE_linkstitch::~OE_linkstitch()
{
	stitchStart->removeDependency(this);
	stitchEnd->removeDependency(this);
}

void OE_linkstitch::persist(Pakal::Archive* archive)
{
	OE_stitchs::persist(archive);

	archive->set_type_name("OE_linkstitch");
	archive->refer("stitchStart", stitchStart);
	archive->refer("stitchEnd", stitchEnd);
	archive->value("stepPts", stepPts);
}

void  OE_linkstitch::setStitchStart(OE_stitchs* stitch)
{
	if (stitchStart)
	{
		stitchStart->removeDependency(this);
	}
	stitchStart = stitch;
	stitch->addDependency(this);
	setNeedRefresh();
}

void  OE_linkstitch::setStitchEnd(OE_stitchs* stitch)
{
	if (stitchEnd)
	{
		stitchEnd->removeDependency(this);
	}
	stitchEnd = stitch;
	stitch->addDependency(this);
	setNeedRefresh();
}

OE_stitchs* OE_linkstitch::getStitchStart()
{
	return stitchStart;
}

OE_stitchs* OE_linkstitch::getStitchEnd()
{
	return stitchEnd;
}

vector_2d OE_linkstitch::getStepPt( int pos)
{
	std::list<vector_2d>::iterator it;
	it = stepPts.begin();
	advance(it,pos);
	return *it;
}

void OE_linkstitch::setStepPts( std::list<vector_2d> pts)
{
	stepPts.clear();
	stepPts = pts;
}

void OE_linkstitch::setStepPt( int pos, vector_2d pt)
{
	std::list<vector_2d>::iterator it;
	it = stepPts.begin();
	advance(it,pos);
	*it = pt;
	setNeedRefresh();
}

void OE_linkstitch::addStepPt( int pos, vector_2d pt)
{
	std::list<vector_2d>::iterator it;
	it = stepPts.begin();
	advance(it,pos);
	stepPts.insert(it, pt);
	setNeedRefresh();
}

void OE_linkstitch::delStepPt( int pos)
{
	std::list<vector_2d>::iterator it;
	it = stepPts.begin();
	advance(it,pos);
	stepPts.erase(it);
	setNeedRefresh();
}

bool OE_linkstitch::check()
{
	return stitchStart && stitchEnd &&
	       stitchStart->check() && stitchEnd->check() &&
	       stitchStart->getNpts() && stitchEnd->getNpts();
}

//void OE_linkstitch::refresh(){}
void OE_linkstitch::refresh(float dpi, bool force)
{
	stitchStart->refresh(dpi, force);
	stitchEnd->refresh(dpi, force);

	if (!check() || !(needRefresh && force))
	{
		return;
	}

	stitchStart->refresh(dpi, force);
	stitchEnd->refresh(dpi, force);
	thread = stitchStart->getThread();
	vector_2d tmpPt;

	std::vector<vector_2d> outPts;
	stitchStart->getPoint(stitchStart->getNpts()-1, &tmpPt);
	outPts.push_back(tmpPt);

	outPts.insert(outPts.end(), stepPts.begin(), stepPts.end());

	stitchEnd->getPoint(0, &tmpPt);
	outPts.push_back(tmpPt);

	stitchPostProcess(outPts);

	needRefresh = false;
}

void OE_linkstitch::delDependency(OE_base* object)
{
	if (stitchStart == object)
	{
		stitchStart = nullptr;
	}
	if (stitchEnd == object)
	{
		stitchEnd = nullptr;
	}
}

void OE_linkstitch::refreshDependency()
{
	if (stitchStart)
	{
		stitchStart->refreshDependency();
		stitchStart->addDependency(this);
	}
	if (stitchEnd)
	{
		stitchEnd->refreshDependency();
		stitchEnd->addDependency(this);
	}
}

void OE_linkstitch::move(vector_2d offset)
{
	std::list<vector_2d>::iterator pt = stepPts.begin();
	while (pt != stepPts.end())
	{
		*pt = *pt + offset;
		pt++;
	}
	setNeedRefresh();
}

void OE_linkstitch::scale(vector_2d ratio, vector_2d pos)
{
	std::list<vector_2d>::iterator pt = stepPts.begin();
	while (pt != stepPts.end())
	{
		*pt = pos + (*pt - pos)*ratio;
		pt++;
	}
	setNeedRefresh();
}

