/*
Minetest-c55
Copyright (C) 2011 celeron55, Perttu Ahola <celeron55@gmail.com>
Copyright (C) 2011 Kahrl <kahrl@gmx.net>

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 2 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, write to the Free Software Foundation, Inc.,
51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/

#include "craftitemdef.h"
#include "irrlichttypes.h"
#include "log.h"
#include <sstream>
#include "utility.h"

CraftItemDefinition::CraftItemDefinition():
	imagename(""),
	cookresult_item(""),
	furnace_cooktime(3.0),
	furnace_burntime(-1.0),
	usable(false),
	liquids_pointable(false),
	dropcount(-1),
	stack_max(99)
{}

std::string CraftItemDefinition::dump()
{
	std::ostringstream os(std::ios::binary);
	os<<"imagename="<<imagename;
	os<<", cookresult_item="<<cookresult_item;
	os<<", furnace_cooktime="<<furnace_cooktime;
	os<<", furnace_burntime="<<furnace_burntime;
	os<<", usable="<<usable;
	os<<", liquids_pointable="<<liquids_pointable;
	os<<", dropcount="<<dropcount;
	os<<", stack_max="<<stack_max;
	return os.str();
}

void CraftItemDefinition::serialize(std::ostream &os)
{
	writeU8(os, 0); // version
	os<<serializeString(imagename);
	os<<serializeString(cookresult_item);
	writeF1000(os, furnace_cooktime);
	writeF1000(os, furnace_burntime);
	writeU8(os, usable);
	writeU8(os, liquids_pointable);
	writeS16(os, dropcount);
	writeS16(os, stack_max);
}

void CraftItemDefinition::deSerialize(std::istream &is)
{
	int version = readU8(is);
	if(version != 0) throw SerializationError(
			"unsupported CraftItemDefinition version");
	imagename = deSerializeString(is);
	cookresult_item = deSerializeString(is);
	furnace_cooktime = readF1000(is);
	furnace_burntime = readF1000(is);
	usable = readU8(is);
	liquids_pointable = readU8(is);
	dropcount = readS16(is);
	stack_max = readS16(is);
}

class CCraftItemDefManager: public IWritableCraftItemDefManager
{
public:
	virtual ~CCraftItemDefManager()
	{
		clear();
	}
	virtual const CraftItemDefinition* getCraftItemDefinition(const std::string &itemname) const
	{
		core::map<std::string, CraftItemDefinition*>::Node *n;
		n = m_item_definitions.find(itemname);
		if(n == NULL)
			return NULL;
		return n->getValue();
	}
	virtual std::string getImagename(const std::string &itemname) const
	{
		const CraftItemDefinition *def = getCraftItemDefinition(itemname);
		if(def == NULL)
			return "";
		return def->imagename;
	}
	virtual bool registerCraftItem(std::string itemname, const CraftItemDefinition &def)
	{
		infostream<<"registerCraftItem: registering CraftItem \""<<itemname<<"\""<<std::endl;
		/*core::map<std::string, CraftItemDefinition*>::Node *n;
		n = m_item_definitions.find(itemname);
		if(n != NULL){
			errorstream<<"registerCraftItem: registering item \""<<toolname
					<<"\" failed: name is already registered"<<std::endl;
			return false;
		}*/
		m_item_definitions[itemname] = new CraftItemDefinition(def);
		return true;
	}
	virtual void clear()
	{
		for(core::map<std::string, CraftItemDefinition*>::Iterator
				i = m_item_definitions.getIterator();
				i.atEnd() == false; i++){
			delete i.getNode()->getValue();
		}
		m_item_definitions.clear();
	}
	virtual void serialize(std::ostream &os)
	{
		writeU8(os, 0); // version
		u16 count = m_item_definitions.size();
		writeU16(os, count);
		for(core::map<std::string, CraftItemDefinition*>::Iterator
				i = m_item_definitions.getIterator();
				i.atEnd() == false; i++){
			std::string name = i.getNode()->getKey();
			CraftItemDefinition *def = i.getNode()->getValue();
			// Serialize name
			os<<serializeString(name);
			// Serialize CraftItemDefinition and write wrapped in a string
			std::ostringstream tmp_os(std::ios::binary);
			def->serialize(tmp_os);
			os<<serializeString(tmp_os.str());
		}
	}
	virtual void deSerialize(std::istream &is)
	{
		// Clear everything
		clear();
		// Deserialize
		int version = readU8(is);
		if(version != 0) throw SerializationError(
				"unsupported CraftItemDefManager version");
		u16 count = readU16(is);
		for(u16 i=0; i<count; i++){
			// Deserialize name
			std::string name = deSerializeString(is);
			// Deserialize a string and grab a CraftItemDefinition from it
			std::istringstream tmp_is(deSerializeString(is), std::ios::binary);
			CraftItemDefinition def;
			def.deSerialize(tmp_is);
			// Register
			registerCraftItem(name, def);
		}
	}
private:
	// Key is name
	core::map<std::string, CraftItemDefinition*> m_item_definitions;
};

IWritableCraftItemDefManager* createCraftItemDefManager()
{
	return new CCraftItemDefManager();
}