/*
    Copyright (C) 2011 Marcos Alba Soler (marcos dot alba at estudiants dot urv dot cat)
                       Jaume Singla Valls (jaume dot singlavalls at gmail dot com)

    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.

    This program is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.

    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/

#ifndef KERNEL_H
#define KERNEL_H

#include <iostream>
#include "mod_sdl/sdlsurfacetype.h"
#include <boost/shared_ptr.hpp>
namespace Kernel {
	class AbstractKernel;
	class AbstractKernelFactory;
	
	/*
	 *Abstract Delay Node, is the abstract class, for use the three types of delay, depending of xml configuration.
	 *  The declaration of the three clases, are embedded in delay.h. 
	 */
	class AbstractDelayNode;
	
}
#include "../XMLImplementation/Implementation.h"
#include "../Pictures/Pictures.h"

namespace Kernel{

	enum kernelType {NIL,COLLAGE,CICLIC};
	/*
	 * The abstract class Kernel, we use as an Interface. It has background animation implementation.
	 *
	 */
	class AbstractKernel{
		public:
			AbstractKernel(boost::shared_ptr<XMLImplementation::Module> activity);
			virtual ~AbstractKernel();

			virtual std::string getName()=0;
			virtual std::vector<boost::shared_ptr<Pictures::PictureNode> > parseMotion(float motion)=0;
			/*
			 * Clear the status of kernel (is used when we change of kernel). 
			 */
			virtual void clear()=0;
			virtual void setWindowSize(int x, int y);
			
			/*
			 * Obtain the background picture, it can be null.
			 */
			SmartPtr<mod_sdl::CTypeSDLSurface> getBackground(float time);
			/*
			 * Is used for know if this module has a valida background configuration, or don't has it. 
			 */
			bool hasBackground();
			
			/*
			 * these methods are only valids for kernelCollage, and they are the value of the pin in the mod_collage
			 */
			virtual void SetMaximumOnScreen(unsigned int) { }
			virtual unsigned int GetMaximumInScreen() const { return 0; }

			virtual void SetVanish (bool) { }
			virtual bool GetVanish() const { return false; }

		protected:
			boost::shared_ptr<XMLImplementation::Module> m_module;
			int m_old_x,m_old_y;
		private:			
			float m_interval;
			float m_elapsedTime;

			int   m_imageShow;
			std::vector<SmartPtr<mod_sdl::CTypeSDLSurface> > m_backgroundList;
			std::vector<SmartPtr<mod_sdl::CTypeSDLSurface> > m_backgroundResizedList;
	};
	
	
	/*
	 *Collage Kerne, is the kernel that do the graphic collage, all values are random.
	 *	It has a vector, that is a fifo queue, we insert objects at the end, and delete objects in the beginning.
	 */
	class CollageKernel:public AbstractKernel {
		public:
			CollageKernel(boost::shared_ptr<XMLImplementation::Module> activity);
			virtual ~CollageKernel();
			
			virtual void SetMaximumOnScreen(unsigned int val) { 
				m_maxOnScreen= val; 
			}
			virtual unsigned int GetMaximumOnScreen() const { return m_maxOnScreen; }
			

			virtual void SetVanish (bool v) { 
				m_vanish= v; 
			}
			virtual bool GetVanish() const { return m_vanish; }

			virtual std::vector<boost::shared_ptr<Pictures::PictureNode> > parseMotion(float increment);
			virtual void clear();
			virtual void setWindowSize(int x, int y);
			
			virtual std::string getName();
		private:
			bool m_vanish;
			unsigned int m_maxOnScreen;
			int* m_indexPictures;
			int m_count;
			std::vector<boost::shared_ptr<Pictures::PictureNode> > 
				m_objectsInScreen, m_objectsIncoming, m_objectsOutgoing;			
	};
	
	/*
	 *CiclicKernel, is the implementation of the need by the scenes that everything show the same images, with only the transitions.
	 *	It is dessign, for use the delay class, and only modify the object with the transitions.
	 */
	class CiclicKernel : public AbstractKernel{
	public:
		CiclicKernel(boost::shared_ptr<XMLImplementation::Module> mod);
		virtual ~CiclicKernel();
		virtual std::vector<boost::shared_ptr<Pictures::PictureNode> > parseMotion(float motion);
		virtual std::string getName();
		virtual void clear();
		virtual void setWindowSize(int x, int y);
	protected:
		std::vector<boost::shared_ptr<Pictures::PictureNode> > m_objects;
		std::vector<boost::shared_ptr<AbstractDelayNode> > m_objWithDelays;
		XMLImplementation::delayType m_delayType;
	};
	
	/*
	 * Only an interface for the collage factory and ciclick kernel
	 */
	class AbstractKernelFactory{
	public:
		static boost::shared_ptr<AbstractKernelFactory> getKernelFactory(kernelType kt);
		virtual boost::shared_ptr<AbstractKernel> getKernel(boost::shared_ptr<XMLImplementation::Module> mod)=0;
	};

	/*
	 * The factory class for the collage kernel.
	 */
	class CollageKernelFactory : public AbstractKernelFactory{
	public:
		boost::shared_ptr<AbstractKernel> getKernel(boost::shared_ptr<XMLImplementation::Module> mod);
	};
	
	/*
	 * The Factory class for the Ciclick kernel.
	 */
	class CiclicKernelFactory : public AbstractKernelFactory{
	public:
		boost::shared_ptr<AbstractKernel> getKernel(boost::shared_ptr<XMLImplementation::Module> mod);
	};
}

#endif // KERNEL_H
