
/*!
\file
\brief Distributed Traffic light Control Scenario 
\author Vasek Smidl 

 */

#include "base/user_info.h"
#include "base/loggers.h"
#ifdef _WIN32
#include "aimsun_bdm/aimsun_ds.h"
#else 
#include "aimsun_bdm/aimsun_fake.h"
#endif
#include "traffic_agent.h"

using namespace bdm;

int main ( int argc, char* argv[] ) {
	const char *fname;
	if ( argc>1 ) {fname = argv[1];	}
	else { cout << "Missing configuration file.\n Usage: \n $> estimator config_file.cfg"<<endl; abort(); }
	UIFile Cfg ( fname );

	// SYSTEM TO CONTROL
	AimsunDS Ds ( Cfg ); // Mostly hard-coded so far

	// AGENTS
	Array<shared_ptr<Participant> > Ags;
	UI::get ( Ags,Cfg, "agents" );

	// LOGGER
	shared_ptr<logger> L = UI::build <logger>( Cfg, "logger" );
	if (!L) {L=new stdlog();} // DEFAULT LOGGER <== poor choice, use better ones

	Config MsgStore;
	MsgStore.setAutoConvert(true);
	Setting& Queue = MsgStore.getRoot().add("queue", Setting::TypeList);

	// REGISTER ACTIVE OBJECTS IN LOGGER
	Ds.log_register ( *L, "DS" );
	for ( int i=0; i<Ags.length(); i++ ) {
		Ags ( i )->log_register ( *L,Ags(i)->_name() ); // estimate
		Ags ( i )->ds_register(Ds);            // allows agents to update their datalinks
	}
	L->init();

	vec glob_dt(Ds._drv()._dsize() );
	vec glob_ut(Ds._urv()._dsize() );

	// INITIALISATION OF UT
	glob_ut[ 0] = 80; // cycle time
	glob_ut[ 1] = 60; // offset 495
	glob_ut[ 2] = 30; // ut[2]+ut[3]+ut[4] has to sum up to ut[0]
	glob_ut[ 3] = 30;
	glob_ut[ 4] = 20;
    glob_ut[ 8] = 40; // offset 601
	glob_ut[ 9] = 30; // ut[9]+ut[10]+ut[11] has to sum up to ut[0]
	glob_ut[10] = 30;
	glob_ut[11] = 20;

	for ( int tK=0; tK < Ds.max_length(); tK++ ) {
		Ds.log_write ( ); // write stuff to 
		Ds.getdata(glob_dt);
		
		for ( int i=0; i<Ags.length(); i++ ) {
			Ags(i) -> adapt(glob_dt);
		}
		for ( int i=0; i<Ags.length(); i++ ) {
			Ags(i) -> broadcast(Queue);
		}
		//DBG
		MsgStore.writeFile("xxx");
		// parse message queue
		for ( int m=Queue.getLength()-1; m>=0; m-- ) { // go backwards - last mesages are discarded
			for ( int i=0; i<Ags.length(); i++ ) {
				Setting& msg=Queue[m];
				string m_to=msg["to"];
				if (m_to==Ags(i)->_name()) {
					Ags(i)->receive(msg);
					Queue.remove(m);
					break;
					// message delivered;
				}
			}
		}
		if (Queue.getLength()>0){bdm_error("undelivered messages - probably unknown neighbours");}
		
		for ( int i=0; i<Ags.length(); i++ ) {
			Ags(i) -> act(glob_ut);
		}
		
		L->step();
		Ds.write(glob_ut);
		Ds.step();							// simulator step
		
		for ( int i=0; i<Ags.length(); i++ ) {
			Ags(i) -> log_write();
			Ags(i) -> step();
		}
		
	}

	L->finalize();

	return 0;
}

