/***************************** LICENSE START ***********************************

 Copyright 2012 ECMWF and INPE. This software is distributed under the terms
 of the Apache License version 2.0. In applying this license, ECMWF does not
 waive the privileges and immunities granted to it by virtue of its status as
 an Intergovernmental Organization or submit itself to any jurisdiction.

 ***************************** LICENSE END *************************************/

#ifndef IconFactory_H
#include "IconFactory.h"
#endif

#ifndef IconClass_H
#include "IconClass.h"
#endif

#ifndef IconInfo_H
#include "IconInfo.h"
#endif

#ifndef Unknown_H
#include "Unknown.h"
#endif

#ifndef Folder_H
#include "Folder.h"
#endif

#ifndef Request_H
#include "Request.h"
#endif

#ifndef Temporary_H
#include "Temporary.h"
#endif

static map<string,IconFactory*>* makers = 0;

IconFactory::IconFactory(const string& name)
{
	if(makers == 0)
		makers = new map<string,IconFactory*>;

	(*makers)[name] = this;
}

IconFactory::~IconFactory()
{
	// Not called
}

IconObject* IconFactory::create(Folder* parent,const string& name,const IconClass& kind,IconInfo *info)
{


	IconObject* o = 0;

	//cout << "IconFactory::create " << name << endl;

	// Try class, then type
	map<string,IconFactory*>::iterator j = makers->find(kind.name());
	if(j == makers->end()) j = makers->find(kind.type());
	if(j == makers->end())
	{
		//cout << "oops, no factory for " << kind.type() << endl;
		// o = new Unknown(parent,kind,name,info);
		o = 0;
	}
	else o =  (*j).second->make(parent,kind,name,info);

	if(o != 0)
	{
		parent->adopt(o);
		o->createFiles();
	}

	return o;

}

IconObject* IconFactory::create(Folder* parent,const string& name,const IconClass& kind)
{
	return create(parent,name,kind,0);
}

IconObject* IconFactory::create(Folder* parent,const string& name)
{
	Path path = parent->path(); 
	Path file = path.add(name);
	Path dot  = path.add(string(".") + name);

	//cout << "create " << name << " in " << *parent << endl;
	//cout << file << endl;
	//cout << dot << endl;

	Request info(dot);

	const char* type = info("ICON_CLASS");
	const IconClass&  kind = (type && *type) ? IconClass::find(type) : IconClass::guess(file);

	if(!info) {
		info = Request("USER_INTERFACE");
		info("ICON_CLASS") = kind.name().c_str();
	}

	return create(parent,name,kind,new IconInfo(info));
}	

IconObject* IconFactory::create(const string& name,const IconClass& kind)
{
	IconObject* o = IconObject::search(name);
	if(o) return o;

	//cout << "IconFactory::create " << name << endl;
	string dir  = mdirname(name.c_str());
	string base = mbasename(name.c_str());
	Folder* f   = dynamic_cast<Folder*>(create(dir,IconClass::find("FOLDER")));
	return f?create(f,base,kind):0;
}

IconObject* IconFactory::create(IconObject* o,const Request& r,
	const IconClass* c)
{
	return new Temporary(o,r,c);
}

IconObject* IconFactory::create(Folder* parent,const Request& r)
{
	const char* kind = r.getVerb();
	const char* name = r("_NAME");

	string kind1(kind);    //it is needed on alpha
	const IconClass& c = IconClass::find(kind1);

// The command below was causing memory problems on alpha.
// Therefore, it was re-coded in a different way
//	string n = name?mbasename(name):c.defaultName();
	string n;
	if (name)
	      n = mbasename(name);
	else
	      n = c.defaultName();

	n = parent->uniqueName(n);

	IconObject* o = create(parent,n,c);

	r.save(o->path());
	return o;
}

