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

#ifndef RequestPanel_H
#include "RequestPanel.h"
#endif

#ifndef EditorFactory_H
#include "EditorFactory.h"
#endif

#ifndef IconObject_H
#include "IconObject.h"
#endif

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

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

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

#ifndef RequestPanelLine_H
#include "RequestPanelLine.h"
#endif


RequestPanel::RequestPanel(const IconClass& kind, Widget parent, 
	const char* name): 
	apply_(false),
	class_(kind)
{
	create(parent,  (char*) name);
	scan();
	Manage();
}

RequestPanel::~RequestPanel()
{
	XtDestroyWidget(xd_rootwidget());
}

const IconClass& RequestPanel::iconClass()
{
	return class_;
}

void RequestPanel::scan() 
{

   	class_.language().scan(*this);

	Dimension a,b;
	Dimension ma = 0,mb = 0;

	for(vector<RequestPanelItem*>::iterator j = items_.begin(); j != items_.end(); ++j)
	{	
		RequestPanelItem* p = (*j);
		p->getSizes(a,b);
		if(a>ma) ma = a;
		if(b>mb) mb = b;
	}
	
	for(vector<RequestPanelItem*>::iterator j = items_.begin(); j != items_.end(); ++j)
	{	
		RequestPanelItem* p = (*j);
		p->setSizes(ma,mb);
	}

}

Widget  RequestPanel::where() 
{
	return rowcol_;
}
Widget  RequestPanel::main() 
{
	return UIRequestPanel;
}

void RequestPanel::merge(IconObject* o)
{
	// Merge requests. The input request is not expanded; therefore,
	// it contains only the non-default parameters. As a consequence,
	// only those parameters, plus the ones that are set in the
	// output request, will be merged.
	Request r1 = request();
	Request r  = class_.language().expand(r1,EXPAND_DEFAULTS,false);
	r.merge(o->request());

	// Move back to the default those values that are no longer valid
	Request rr = class_.language().expand(r,EXPAND_DONT_FAIL);
	request(rr);

	// Update UI
	call(&RequestPanelItem::update);
}

void RequestPanel::replace(IconObject* o)
{
	request(o->request());
	call(&RequestPanelItem::update);
}

void RequestPanel::next(const Parameter& p)
{
	RequestPanelLine::build(where(),*this,p);
}

void RequestPanel::call(Method proc)
{
	for(vector<RequestPanelItem*>::iterator j = items_.begin(); j != items_.end(); ++j)
	{	
		RequestPanelItem* o = *j;
		(o->*proc)();
	}
}

void RequestPanel::apply() 
{
      apply_ = true;
      call(&RequestPanelItem::apply);
      apply_ = false;
}

const Request& RequestPanel::request(long flags) 
{	
	map<long,Request>::iterator j = cache_.find(flags);
	if(j != cache_.end()) return (*j).second;
	return cache_[flags] = class_.language().expand(cache_[EXPAND_2ND_NAME],flags);
}

void RequestPanel::request(const Request& r, long flags)
{
	cache_.clear();
	cache_[EXPAND_2ND_NAME] = class_.language().expand(r,EXPAND_2ND_NAME);
	if ( flags != EXPAND_2ND_NAME )
		cache_[flags] = class_.language().expand(r,flags);
}

void RequestPanel::edit(IconObject *o)
{	
	for(vector<RequestPanelItem*>::iterator j = items_.begin(); j != items_.end(); ++j)
		(*j)->edit(o);
}

void RequestPanel::close() 
{
	call(&RequestPanelItem::update);
	cache_.clear();
}

void RequestPanel::reset(IconObject *o)
{	
	request(o->request()); 
	edit(o);
	call(&RequestPanelItem::reset);
}

void RequestPanel::registerObserver(RequestPanelItem* observer) 
{
	items_.push_back(observer);
}

void RequestPanel::changed(RequestPanelItem& p,bool canUpdate)
{
	Request r = request();
	p.set(r);
	request(r);

	if(!apply_) 
		if(canUpdate) 
			call(&RequestPanelItem::update);
}

void RequestPanel::set(const char* p,const string& v)
{
	Request r = request();
	r(p) = v.c_str();
	request(r);

	if(!apply_) call(&RequestPanelItem::update);
}

void RequestPanel::clear(const char* p)
{
	Request r = request();
	r.unsetParam(p);
	request(r);

	if(!apply_) call(&RequestPanelItem::update);
}

