/***************************** 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 Basic_H
#include "Basic.h"
#endif

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

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

#ifndef Language_H
#include "Language.h"
#endif

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

#include "Dependancy.h"

#include "mars.h"

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

#ifndef Tokenizer_H
#include "Tokenizer.h"
#endif

#ifndef Log_H
#include "Log.h"
#endif



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

Basic::~Basic()
{
}

void Basic::doubleClick()
{
	edit();
}

set<string> Basic::can()
{
	return IconObject::can();
}

void Basic::createFiles()
{
	IconObject::createFiles();
	Path p = path();
	if(!p.exists())
		p.saveText(className());
}

Request Basic::request() const
{
	Request r(path());
	return language().expand(r);

}

void Basic::request(const Request& r)
{
	Request req = language().expand(r,EXPAND_NO_DEFAULT|EXPAND_2ND_NAME);
	req.save(path());
}

class BasicDependancy : public Dependancy {

	IconObjectH object_;
	string param_;
	int n_;
	bool ok_;
	Request request_;

	virtual Task* action(const Action&);
	virtual void success(const Request&);
	virtual void failure();
public:
	BasicDependancy(IconObject*,const string&,int);
	~BasicDependancy();

	int n()                  { return n_;       }
	const string& param()    { return param_;   }
	const Request& request() { return request_; }
};

BasicDependancy::BasicDependancy(IconObject *o,const string& param,int n):
	object_(o),
	param_(param),
	n_(n),
	request_(""),
	ok_(false)
{
}

Task* BasicDependancy::action(const Action& a)
{
	return object_->action(a);
}

void BasicDependancy::success(const Request& r)
{
	ok_      = true;	
	request_ = r;
}

void BasicDependancy::failure()
{
	ok_      = false;
}

BasicDependancy::~BasicDependancy()
{
}




const set<DependancyH>& Basic::dependancies()
{

	if(dependancies_.size())
		return dependancies_;

	dependancies_.clear();

	Request r = request();

	vector<string> icons = language().interfaces("icon");

	for(vector<string>::iterator j = icons.begin() ; j != icons.end(); ++j)
	{
		int i = 0;
		vector<IconObjectH> sub = subObjects(*j,r);

		for(vector<IconObjectH>::iterator k = sub.begin(); k != sub.end(); ++k)
			dependancies_.insert(new BasicDependancy(*k,*j,i++));
	}

	return dependancies_;
}


Request Basic::fullRequest() const
{
	Request r = request();

	typedef map<int,Request> Map1;
	typedef map<string,Map1> Map2;

	Map2 m;

	for(set<DependancyH>::const_iterator k = dependancies_.begin(); k != dependancies_.end() ; ++k)
	{
		BasicDependancy* b = dynamic_cast<BasicDependancy*>((Dependancy*)*k);
		const string& p  = b->param();
		int n            = b->n();
		const Request& r = b->request();

		m[p][n] = r;
	}

	for(Map2::iterator j = m.begin(); j != m.end(); ++j)
	{
		const string& param = (*j).first;
		const Map1&   reqs  = (*j).second;

		::request* empty = 0;
		MvRequest s(empty);

		for(Map1::const_iterator i = reqs.begin(); i != reqs.end() ; ++i)
			s = s + (*i).second;

		r(param.c_str()) = s;
		
	}

	cout << "---> Basic fullrequest" << endl;
	r.print();
	cout << "<--- Basic fullrequest" << endl;

	return r;
}

bool Basic::rename(const string& newname)
{
	Request r = request();

	cout << "Basic::rename" << endl;
	r.print();

	vector<string> icons = language().interfaces("icon");
	map<string,vector<IconObjectH> > sub;

	for(vector<string>::iterator j = icons.begin() ; j != icons.end(); ++j)
		sub[*j] = subObjects(*j,r);

	if(!IconObject::rename(newname))
		return false;

	for(vector<string>::iterator j = icons.begin() ; j != icons.end(); ++j)
		subObjects(*j,sub[*j],r);

	r.print();
	request(r);
	return true;
}

IconObject* Basic::clone(Folder *folder)
{
	Basic* other = dynamic_cast<Basic*>(IconObject::clone(folder));
	if( !other )
	  {
	    //-- this branch is for finding out why 'other' may be 0!
	    //-- i.e. use these lines to set breakpoint in debugger!!

	    string s("MvUI/Basic::clone()");
	    Log::info(s) << "internal error: NULL ptr!" << endl;

	    return 0;  //-- probably we should not do this...
	  }

	vector<string> icons = language().interfaces("icon");

	Request r = other->request();
	r.print();

	Folder* e = this->embeddedFolder(true);
	Folder* f = other->embeddedFolder(true);

	map<string,vector<IconObjectH> > sub;

	for(vector<string>::iterator j = icons.begin() ; j != icons.end(); ++j)
	{
		vector<IconObjectH> v = other->subObjects(*j,r);

		for(vector<IconObjectH>::iterator k = v.begin() ; k != v.end(); ++k)
		{
			if(e->ancestor(*k))
			{
				string name = relativeName(*k);
				Tokenizer parse("/");
				vector<string> n;
				parse(name,n);

				cout << '[' << name << ']' << endl;
				
				IconObject *o = f;
				for(int i = 1; i < n.size() && o; i++)
				{
					cout << "SEARCH: " << n[i] << " in " << o->fullName() << endl;
					o = o->find(n[i]);
					if(o) cout << "FOUND: " << o->fullName() << endl;
					else
						cout << "NOTFOUND" << endl;

				}

				if(o) {
					cout << "CLONE: " << (*k)->fullName() << endl;
					*k = o;
					cout << "   IS: " << (*k)->fullName() << endl;
				}
			}
		}

		sub[*j] = v;
	}


	for(vector<string>::iterator j = icons.begin() ; j != icons.end(); ++j)
		other->subObjects(*j,sub[*j],r);

	r.print();
	other->request(r);

	return other;
}

static IconMaker<Basic> maker1("Data");
static IconMaker<Basic> maker2("Window");
static IconMaker<Basic> maker3("Visdef");
static IconMaker<Basic> maker4("View");
static IconMaker<Basic> maker5("Preference");
