#include "mof/widget/Effect.hpp"
#include <map>
#include "mof/Sprite.hpp"
#include "mof/Drawable.hpp"
#include "mof/utilities.hpp"
#include <stdexcept>

typedef std::map<mof::tstring , mof::Sprite*> SpriteMap;
typedef std::pair<mof::tstring , mof::Sprite*> SpriteMapPair;
typedef std::map<mof::tstring , mof::Drawable*> DrawableMap;
typedef std::pair<mof::tstring , mof::Drawable*> DrawableMapPair;


struct mof::Effect::Impl
{
	SpriteMap spriteMap;
	DrawableMap drawableMap;

	Impl(){

	}

	~Impl(){
		deleteAll();
	}

	void deleteAll(){
        foreach(DrawableMapPair pair , drawableMap){
			delete pair.second;
		}
		drawableMap.clear();

		foreach(SpriteMapPair pair , spriteMap){
			delete pair.second;
		}
		spriteMap.clear();
	}
};


mof::Effect::Effect()
: m_pImpl(new Impl())
{
}

mof::Effect::~Effect(){
}

mof::Sprite* mof::Effect::getSpriteByName(const mof::tstring &name) {
	SpriteMap::iterator result = m_pImpl->spriteMap.find(name);
	if(result == m_pImpl->spriteMap.end())throw std::invalid_argument(name + "is not exists");
	return result->second;
}

void mof::Effect::addSprite(const mof::tstring& name , mof::Sprite* pSprite){
	SpriteMap::iterator result = m_pImpl->spriteMap.find(name);
	if(result != m_pImpl->spriteMap.end())throw std::invalid_argument(name + "is already exists");
	m_pImpl->spriteMap.insert(SpriteMapPair(name , pSprite));
}
		
void mof::Effect::addDrawable( const mof::tstring& name , mof::Drawable* pDrawable )
{
	DrawableMap::iterator result = m_pImpl->drawableMap.find(name);
	if(result != m_pImpl->drawableMap.end())throw std::invalid_argument(name + "is already exists");
	m_pImpl->drawableMap.insert(DrawableMapPair(name , pDrawable));
}

void mof::Effect::remove(const mof::tstring& name ){
    {
        SpriteMap::iterator result = m_pImpl->spriteMap.find(name);
	    if(result != m_pImpl->spriteMap.end())
        {
            m_pImpl->spriteMap.erase(name);
            return;
        }
    }
    {
        DrawableMap::iterator result = m_pImpl->drawableMap.find(name);
        if(result != m_pImpl->drawableMap.end())
        {
            m_pImpl->drawableMap.erase(name);
            return;
        }
    }
	throw std::invalid_argument(name + "is not exists");
}

void mof::Effect::deleteAll(){
	m_pImpl->deleteAll();
}

void mof::Effect::draw() const
{
    foreach(DrawableMapPair pair , m_pImpl->drawableMap){
		pair.second->draw();
	}
	foreach(SpriteMapPair pair , m_pImpl->spriteMap){
		pair.second->draw();
	}
}


void mof::Effect::update(){
	foreach(SpriteMapPair pair , m_pImpl->spriteMap){
		pair.second->update();
	}
}


