/*
    Copyright (C) 2011 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 PICTURES_H
#define PICTURES_H


#include "spcore/basictypes.h"

#include "mod_sdl/sdlsurfacetype.h"
#include <boost/shared_ptr.hpp>

#include <iostream>

namespace Pictures{
	/* 
	 *	Extracted from file SDL_gfxBlitFunc of SDL_gfx library with LGPL (c) and author A. Schiffler
	 *
	 *	We need this for problems with the actual version of the library, it don't implement this.
	 *	The original Name is SDL_gfxMultiplyAlpha
	 */
	int SDL_gfxMultiplyAlpha2(SDL_Surface *src, Uint8 a);
	
	
	class PictureNode;
	
	/**
	 * Initialy this was a abstract class, but we implementet the IDENTITY transition, that no change the image, with this.
	 * 
	 * The implementation of this, and the subclasses can be found in Transition.cpp
	 * 
	 */
	class PicturesTransition{
		
		public:
			/*
			 * Constructor, it needs the base picture, for obtain the image resized as the proportional size of window.
			 */
			PicturesTransition(boost::shared_ptr<PictureNode> Normal);
			
			/*
			 * Destructor, it release the attributes
			 */
			virtual ~PicturesTransition();
			
			/*
			 * Is used for force a new transition status. Is the proportional of the transition.
			 * 	* status: float 0..1. (the values are descrived in every transition)
			 */
			void setStatus(float status);
			
			/*
			 * Is used for set the coordinates of the image. (only needed in some cases)
			 */
			virtual void setCoordinates(int x, int y);
			
			/*
			 * Is used for know that the window size was changed, (only needed in some cases).
			 */
			virtual void reescale(int w, int h);
			
			/*
			 * only increase the m_status adding i. i can be negative.
			 * 	* i: float. {-1..1}
			 */
			float increase(float i);
			
			/*
			 * Apply transition, in this clase don't do nothing obtaining the identity transition. Is implemented in all PicturesTransition SubClass. 
			 */
			virtual void applyTransition();
			
			/*
			 * Is used for obtain actual status of the transition, same as setStatus, the value returnet was a float fom 0..1
			 */
			float getStatus();
			
			/*
			 * Obtain the picture surface with the transition applied.
			 */
			virtual SmartPtr<mod_sdl::CTypeSDLSurface> getTransition();

		protected:
			boost::shared_ptr<PictureNode> m_Normal;
			float m_status;
			SmartPtr<mod_sdl::CTypeSDLSurface> m_result;
			std::string m_name;
			PicturesTransition();
	};
	
	/*
	 * This transition modify the opacity of the picturenode image. (0=> Transparent, 1=>normal)
	 */
	
	class AlphaTransition: public PicturesTransition{
		public:
			AlphaTransition(boost::shared_ptr<PictureNode> Normal);
			~AlphaTransition();
			virtual void applyTransition();
	};
	
	/*
	 * This transition, scale the picture. (0=> size is 0x0, 1=> size is normal)
	 */
	class ScaleTransition: public PicturesTransition{
		private:
			int m_originalx, m_originaly;
		public:
			ScaleTransition(boost::shared_ptr<PictureNode> Normal);
			~ScaleTransition();
			void setCoordinates(int x, int y);
			virtual void applyTransition();
	};

	/*
	 * Rotate the picture. (0=> the angle of the transition, aplied to the image that will be showed, 1=> the image angle )
	 */
	class RotateTransition: public PicturesTransition{
		private:
			int m_degree;
			int m_originalx, m_originaly;
		public:
			RotateTransition(boost::shared_ptr<PictureNode> Normal, int degree);
			~RotateTransition();
			virtual void applyTransition();
			void setCoordinates(int x, int y);
	};
	
	/*
	 * Cange a picture. (0..0.5=> it shows the picture that has been passed in the constructor, 0.5..1=> displays image from pictureNode)
	 */
	class ChangePictureTransition:public PicturesTransition{
		private:
			std::string m_destinationSrc;
			int m_old_w, m_old_h;
			SmartPtr<mod_sdl::CTypeSDLSurface> m_Base, m_original;
			
		public:
			ChangePictureTransition(boost::shared_ptr<PictureNode> Normal, SmartPtr<mod_sdl::CTypeSDLSurface> surf);
			virtual ~ChangePictureTransition();
			virtual void applyTransition();
			void reescale(int x, int y);
	};

	/*
	 *Move a picture in the screen. (0=> the position of the transition, 1=> the position of the picture)
	 */
	class TranslatePictureTransition:public PicturesTransition{
		private:
			int m_old_w, m_old_h;
			float m_orig_x, m_orig_y;
			int m_origInt_x, m_origInt_y;
			int m_dstInt_x, m_dstInt_y;
			
		public:
			TranslatePictureTransition(boost::shared_ptr<PictureNode> normal, float px,float py);
			~TranslatePictureTransition();
			virtual void applyTransition();
			void reescale(int x, int y);
			void setCoordinates(int,int);
	};
	
	/*
	 * Apply only a part of another transition 2 or more times, in the time of 0-1.
	 */
	class VibratePackagePictureTransition:public PicturesTransition{
		private:
			boost::shared_ptr<PicturesTransition> m_transition;
			float m_percent;
			int m_quantity;
			
		public:
			/** CAREFULL WITH THE WRONG CONSTRUCTOR, it has a error, it works, at the moment... **/
			VibratePackagePictureTransition(boost::shared_ptr<PicturesTransition> transition, float m_percent);
			virtual ~VibratePackagePictureTransition();
			virtual void applyTransition();
			void setCoordinates(int x, int y);
			void reescale(int x, int y);
			SmartPtr<mod_sdl::CTypeSDLSurface> getTransition();
	};
	
	/*
	 * PictureNode, is a class, that we use for administrate the pictures in the screen, it has the transition in, and transition out.
	 * 	And calculate the position from relative position to the absolute position in the screen.
	 * 	(all the methods was documented inside Pictures.cpp)
	 */
	class PictureNode {
	public:
		PictureNode(SmartPtr<const mod_sdl::CTypeSDLSurface> surf, float x, float y, float scale);		
		PictureNode(SmartPtr<const mod_sdl::CTypeSDLSurface> surf, float x, float y, float scale, int width, int height);
		
		~PictureNode();
		void breakCycle();
		
		void setTransitionIn(boost::shared_ptr<PicturesTransition> in, float status=0.0f);		
		void setTransitionOut(boost::shared_ptr<PicturesTransition> out, float status=1.0f);
		
		boost::shared_ptr<PicturesTransition>  getTransitionIn();		
		boost::shared_ptr<PicturesTransition>  getTransitionOut();
		
		void rescale(int width, int height);		
		float getScale();

		SmartPtr<mod_sdl::CTypeSDLSurface> getBase();		
		SmartPtr<mod_sdl::CTypeSDLSurface> getcType();
		
		bool decreaseAlpha();		
		float getStatusTransition();
		
		float increaseTransition(float inc);		
		float decreaseTransition(float dec);
		
		int getStatus();		
		void setStatus(int v);

	private:
		SmartPtr<const mod_sdl::CTypeSDLSurface> m_original;
		SmartPtr<mod_sdl::CTypeSDLSurface> m_Base;
		boost::shared_ptr<PicturesTransition> m_in, m_out;
		
		int m_status;
		unsigned char m_alpha;
		float m_x, m_y;
		float m_scale;
	};
	
}

#endif