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

 Copyright 2014 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 *************************************/

#include "IconFactory.h"

#include "IconClass.h"
#include "IconInfo.h"
//#include "Unknown.h"
#include "Folder.h"

#include "FolderInfo.h"
#include "Request.h"
#include "TemporaryObject.h"

#include <assert.h>

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
}

//For folders name should contain the full path!!!
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::createTemporary(IconObject* o,const Request& r,const IconClass* c)
{
	return new TemporaryObject(o,r,c);
}

/*

//For folders with  no parents the fullpath is needed!
//For folders with parent the relativ name is needed!
IconObject* IconFactory::create(Folder* parent,const string& name,const IconClass& kind,int x, int y)
{
	IconInfo *info=new IconInfo(kind.name(),x,y);
	
	string fileName=name;	
	if(kind.type() == "Folder")
	{
		if(parent)
		{
  			Path path=parent->path(); 		
			fileName = path.add(name).str();
		}		
	}  
		
	return create(parent,fileName,kind,info);
}

IconObject* IconFactory::create(Folder* parent,const string& name,const IconClass& kind)
{
	string fileName=name;	
	if(kind.type() == "Folder")
	{
		if(parent)
		{
  			Path path=parent->path(); 		
			fileName = path.add(name).str();
		}		
	}  
	
	return create(parent,fileName,kind,0);
}

IconObject* IconFactory::create(Folder* parent,const string& name, int x, int y)
{
	FolderInfo* folderInfo=0;
	IconInfo* info=0;	
	string 	dirName, fileName;
	
	if(!parent)
	{
		dirName = string(dirname(name.c_str()));
		fileName = name;
	}
	else
	{  
  		Path path=parent->path(); 		
  		dirName = path.str(); 
		fileName = path.add(name).str();
		folderInfo=parent->folderInfo();
		info=folderInfo->find(name);
	}	

	const IconClass&  ic = (info) ? IconClass::find(info->type()) : IconClass::guess(fileName);
	
	//Folders can be created with no parent. We need to check if the
	//current item is such an already existing object. If it is we set
	//the x/y position for it if it is possible.
	if(ic.type() == "Folder")
	{
	  	IconObject *f=Folder::folder(fileName,false);
		if(f) 
		{
		  	if(info) f->position(info->x(),info->y());
			if(!f->parent() && parent) parent->adopt(f);
			return f;
		}
	}	
	
	
	string iconName=(ic.type() == "Folder")?fileName:name;
		
	//If there is no folderinfo available we see if there is a 
	//dotfile to get the positions
	if(!info)
	{
		Path path(dirName);
	  	Path dot  = path.add(string(".") + name);  		
		Request dotInfo(dot);
		
		if(!dotInfo) 
		{
			dotInfo = Request("USER_INTERFACE");
		}	
		dotInfo("ICON_CLASS") = ic.name().c_str();
		
		info=new IconInfo(dotInfo);
		if(x != 0 || y != 0)
			info->position(x,y);
		
	}
	
	return create(parent,iconName,ic,info);

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

}

*/


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,const IconClass& kind,int x, int y)
{
	IconInfo *info=new IconInfo(kind.name(),x,y);
	return create(parent,name,kind,info);
}

IconObject* IconFactory::create(Folder* parent,const string& name)
{
 	return create(parent,name,IconInfo::undefX(),IconInfo::undefY());
}	

IconObject* IconFactory::create(Folder* parent,const string& name, int x, int y)
{
	FolderInfo* folderInfo=0;
	IconInfo* info=0;	
	string 	dirName, fileName;
		
	Path path=parent->path(); 		
  	dirName = path.str(); 
	fileName = path.add(name).str();
	folderInfo=parent->folderInfo();
	info=folderInfo->find(name);
	
	if(info)
	{
		const IconClass&  ic = IconClass::find(info->type());
		return create(parent,name,ic,info);
	}
	
	//If there is no folderinfo available we see if there is a 
	//dotfile to get the type and the positions
	else
	{	  		
		Path actPath(dirName);
	  	Path dot  = actPath.add(string(".") + name);  		
		Request dotInfo(dot);
		
		//If there is no dotfile we guess the file type
		if(!dotInfo) 
		{
			dotInfo = Request("USER_INTERFACE");
			const IconClass&  ic = IconClass::guess(fileName);
			dotInfo("ICON_CLASS") = ic.name().c_str();
			
			info=new IconInfo(dotInfo);
			if(x != IconInfo::undefX() && y != IconInfo::undefY())
				info->position(x,y);
		
			return create(parent,name,ic,info);	
			
		}	
		else
		{  
			const char* type=dotInfo("ICON_CLASS");
		  	const IconClass&  ic = IconClass::find(type);
		
			info=new IconInfo(dotInfo);
			if(x != IconInfo::undefX() && y != IconInfo::undefY())
				info->position(x,y);
		
			return create(parent,name,ic,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*/)
{
	assert(0);
  
        //MODIF
	return 0;
	//return new Temporary(o,r,c);
}

IconObject* IconFactory::create(Folder* parent,const Request& r,int x, int y)
{	
	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,x,y);

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

