/*
 *  Copyright (C) 2004 Alo Sarv <madcat_@users.sourceforge.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#include <hn/dynobj.h>
#include <hn/log.h>

class Object {
	DECLARE_DYNAMIC_CLASS(0x01, Object, std::istream&, void);
public:
	Object() {
		logMsg("Object()");
	}
	Object(std::istream &) {
		logMsg("Object(std::istream&)");
	}
	Object(int) {
		logMsg("Object(int)");
	}
	virtual ~Object() {
		logMsg("~Object()");
	}
	void f() {
		logMsg("Object::f()");
	}
};
IMPLEMENT_DYNAMIC_CLASS(0x01, Object, std::istream&, void);

int main() {
	logMsg("Testing dynamib objects.");
	int errcount = 0;
	try {
		// typical usage - create using opcode
		Object *o = ObjFactory::instance().create<Object>(0x01);
		delete o;
	} catch (...) {
		logError("Creation using opcode failed! Something is wrong...");
		++errcount;
	}

	// create using string name
	try {
		Object *o = ObjFactory::instance().create<Object>("Object");
		delete o;
	} catch (...) {
		logError("Creation using name failed! Something is wrong...");
		++errcount;
	}

	// try erronous usage - wrong opcode
	try {
		logMsg("Attempting to create an object with wrong opcode.");
		Object *o = ObjFactory::instance().create<Object>(0x02);
		logError("Error -> This shouldn't have worked!");
		++errcount;
		delete o;
	} catch (boost::bad_any_cast &err) {
		logMsg(boost::format("Ok: bad_any_cast thrown: %s") % err.what());
	} catch (std::runtime_error &err) {
		logMsg(boost::format("Ok: std::runtime_error thrown: %s") % err.what());
	} catch (...) {
		logMsg("Ok: Unknown exception thrown.");
	}

	// try erronous usage - wrong string
	try {
		logMsg("Attempting to create an object with wrong name.");
		Object *o = ObjFactory::instance().create<Object>("object");
		logError("Error -> This shouldn't have worked!");
		++errcount;
		delete o;
	} catch (boost::bad_any_cast &err) {
		logMsg(boost::format("Ok: bad_any_cast thrown: %s") % err.what());
	} catch (std::runtime_error &err) {
		logMsg(boost::format("Ok: std::runtime_error thrown: %s") % err.what());
	} catch (...) {
		logMsg("Ok: Unknown exception thrown.");
	}

	boost::any a(&std::cin);
	try {
		logMsg("Attempting to create an object using std::cerr argument.");
		Object *o = ObjFactory::instance().create<Object, std::istream&>(0x01, std::cin);
		logMsg("Ok.");
		delete o;
	} catch (boost::bad_any_cast &err) {
		logError(boost::format("%s") % err.what());
		++errcount;
	} catch (std::runtime_error &err) {
		logError(boost::format("%s") % err.what());
		++errcount;
	} catch (...) {
		logError("Failed.");
		++errcount;
	}
	try {
		logMsg("Attempting to create an object using std::istringstream argument.");
		std::istringstream i;
		Object *o = ObjFactory::instance().create<Object, std::istream&>(0x01, i);
		logMsg("Ok.");
		delete o;
	} catch (boost::bad_any_cast &err) {
		logError(boost::format("%s") % err.what());
		++errcount;
	} catch (std::runtime_error &err) {
		logError(boost::format("%s") % err.what());
		++errcount;
	} catch (...) {
		logError("Failed.");
		++errcount;
	}
	if (errcount == 0) {
		logMsg("All tests passed successfully.");
	} else {
		logMsg(boost::format("%d tests failed.") % errcount);
	}
}