/*
 * 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.
 *
 */

#pragma once

#include "OE_base.h"
#include "OE_utils.h"
#include "OE_thread.h"
#include <stdint.h>
#include <vector>
#include "OE_fstream.h"

#include "OE_pattern.h"

namespace Pakal { class Archive; }

class OE_stitchs : public OE_base
{
	public:
		/** Default constructor */
		OE_stitchs();
		/** Default destructor */
		virtual ~OE_stitchs();

		//virtual bool getNeedRefresh();
		//virtual bool setNeedRefresh(bool value);

		virtual void persist(Pakal::Archive* archive);

		/** \brief to get a point in the stitch. */
		bool getPoint(uint16_t nb, float* x, float* y);
		bool getPoint(uint16_t nb, vector_2d* pt);

		/** \brief return a copy of the array of points*/
		const std::vector<vector_2d>& getPoints();

		/** \brief return the number of points in the stitch (control points, without handles) */
		int getNpts();

		/** \brief to get the thread. */
		OE_thread* getThread();

		/** \brief to set a point in the stitch. */
		bool setPoint(uint16_t nb, float x, float y);

		/** \brief to set the thread. */
		bool setThread(OE_thread* thread);

		/** \brief to add a point at the end of the stitch. */
		bool addPoint( float x, float y);
		bool addPoint( vector_2d pt);

		/** \brief set the max len of a segment */
		bool setMaxLen(float maxLen);
		float getMaxLen();

		/** \brief return an array of point splited to respect the maxLen distance */
		std::vector<vector_2d> stitchMaxLen(std::vector<vector_2d> ptsArray, float maxlen);

		/** \brief process stitches after calculation */
		virtual void stitchPostProcess(std::vector<vector_2d> ptsArray);

		/** \brief return an array of warped stitchs from positions and normals arrays of same size and a pattern
		 *  \brief offset is used to offset the pattern along normal
		 */
		std::vector<vector_2d> warpStitch(std::vector<vector_2d> mainPts, std::vector<vector_2d> normalPts, bool normals,
		                                  OE_pattern* pattern, unsigned patternSteps=1,
		                                  float xOffset=0, float yOffset=0);

		/** \brief calculate the curve bounding box
		 * \param xMin,yMin,xMax,yMax -> pointers to the bouding box variables to set
		 */
		virtual BoundingBox getBound();

		/** \brief check if the stitch is valid. */
		virtual bool check();

		//virtual void refresh();

		virtual void refresh(float dpi, bool force = false) = 0;

		virtual void refreshDependency() {}

		/** \brief move the stitch
		 */
		virtual void move(vector_2d /*offset*/) {}

		/** \brief scale the stitch
		 */
		virtual void scale(vector_2d /*ratio*/, vector_2d /*pos*/) {}

		static float defaultMaxlen;

	protected:
		/** \brief Tight bounding box of the shape [minx,miny,maxx,maxy]. */
		//float bounds[4];

		/** \brief the thread associate to this stitch */
		OE_thread* thread;

		/** \brief the array of stitch points */
		std::vector<vector_2d> pts;

		float maxLen = 0;

		/** \brief check if a point is in a given bounding box
		 * \param pt -> the point
		 * \param bounds -> an array representing the bounding box
		 * \return true if the point is inside the bounding box
		 */
		//static bool ptInBounds( vector_2d pt, float* bounds);
};

