/*
 * 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 <string>
#include <thread>
#include <mutex>
#include "stitchs/OE_stitchs.h"
#include "curves/OE_pointcurve.h"
#include "instructions/OE_instruction.h"
#include "OE_thread.h"
#include "OE_pattern.h"

class OE_actions;

namespace Pakal { class Archive; }

class OE_document
{
	public:
		class ScopeLock : public std::lock_guard<std::recursive_mutex>
		{
			public:
				ScopeLock(OE_document& doc);// : std::lock_guard<std::recursive_mutex>(doc.accessLock) {};
		};
		bool saveToFile(std::string path);
		bool loadFromFile(std::string path);

		/** Default constructor */
		OE_document();
		// OE_document(std::string filename);
		/** Default destructor */
		virtual ~OE_document();
	
		void persist(Pakal::Archive* archive);

		/** \brief the list of stitchs */
		std::list<OE_stitchs*> stitchs;

		/** \brief the list of curves */
		std::list<OE_pointcurve*> curves;
		
		/** \brief the list of threads */
		std::list<OE_thread*> threads;

		/** \brief the list of patterns */
		std::list<OE_pattern*> patterns;
	
		/** \brief the list of selected stitchs */
		std::list<OE_stitchs*> selectedStitchs;

		/** \brief the list of selected curves */
		std::list<OE_pointcurve*> selectedCurves;

		/** \brief the array of points to send to the embroideress */
		std::vector<vector_2d> instPoints;

		/** \brief the array of commands to send to the embroideress */
		std::vector<OE_instruction*> instCommand;

		/** \brief the stack of active actions */
		std::list<OE_actions*> activeActionsStack;

		/** \brief the stack of undoed actions */
		std::list<OE_actions*> undoActionsStack;

		
		/** \brief the current points stitched by the embroideress */
		unsigned int curPoint = 0;
		
		BoundingBox getBound() const;

		vector_2d getHoopSize();
		unsigned int getPulsePerMm();
		vector_2d getZeroPoint();
		void setHoopSize(vector_2d hoopSize);
		void setPulsePerMm(unsigned int pulsePerMm);
		void setZeroPoint(vector_2d zeroPoint);

		bool addCurve(OE_pointcurve* curve);
		bool addStitch(OE_stitchs* stitch);
		bool addThread(OE_thread* thread);

		void removeCurve(OE_pointcurve* curve);
		void removeStitch(OE_stitchs* stitch);
		void removeThread(OE_thread* thread);

		bool refresh();

		void lock(); // lock write
		bool trylock(); // try to lock write, return true on success
		void unlock(); // unlock write

		static std::string getWriteDialogFilters();
		static std::string getReadDialogFilters();

	private:
		/** \brief Width of the document. */
		float width;
	
		/** \brief Height of the document. */
		float height;
	
		unsigned int pulsePerMm = 20;
	
		float scale = 0.50f;
	
		vector_2d hoopSize = vector_2d(150,160) ;
	
		vector_2d zeroPoint = vector_2d(0,0) ;

		std::recursive_mutex accessLock;
};

