#include <map>

class GreenWaveTrafficAgent : public BaseTrafficAgent {
protected:
	double stable_state_loss;
	double best_offset;
	map<string,double> expected;
	map<string,double>::iterator expected_i;
	
	//counts all expected cars to "dest"
	double expected_cars(const string dest) {

		double expected=0.0;

		//finds lanes which lead to "dest"
		for (int i=0;i<lanes.length();i++) {
			for (int j=0;j<lanes(i).outputs.length();j++) {
				if (lanes(i).outputs(j).substr(0,3)==dest) {
					//we have some matching outputs, count cars
					string group = name+"_"+lanes(i).sg;
					ivec index=rv_greentimes.dataind(RV(group,1));
					vec green_time=greentimes(index);

					expected+=lanehs(i)->expected_output(green_time(0));
					
				}
			}
		}
		return expected;
	}

public:
	datalink ds2greentimes;
	vec greentimes;
	RV rv_greentimes;
	
	//! array of existing signal groups
	Array<string> sgs;

	void validate() {
		BaseTrafficAgent::validate();
		action_rv = RV(name+"_offset", 1); // <======= example

		for (int i=0; i<sgs.length();i++) {
			rv_greentimes.add(RV(name+"_"+sgs(i),1));
		}
	}

	void adapt(const vec &glob_dt) {
		BaseTrafficAgent::adapt(glob_dt);
				
		ds2greentimes.filldown(glob_dt,greentimes);
	}

	void broadcast(Setting& set){
			
		//ask neighbours for exptected arrive times
		if (true) {
			for (int i=0; i<neighbours.length(); i++){
				Setting &msg =set.add(Setting::TypeGroup);

				UI::save ( neighbours(i), msg, "to");
				UI::save (name,msg,"from");
				UI::save ( (string)"expected_times_request", msg, "what");
			}
		}


		// broadcast expected cars
		while (!expected.empty()) {
			expected_i=expected.begin();

			Setting &msg =set.add(Setting::TypeGroup);

			UI::save ( expected_i->first, msg, "to");
			UI::save ( name, msg, "from");
			UI::save ( (string)"new_expected_cars", msg, "what");
			//UI::save ( &(rv_neighbours_out(i)), msg, "rv");
			UI::save(expected_i->second, msg, "value");
			expected.erase(expected_i);
		}

	}

	void receive(const Setting &msg){
		string what;
		string to;
		string from;
		double value;
		

		UI::get(what, msg, "what", UI::compulsory);
		UI::get(to, msg, "to", UI::compulsory);
		UI::get(from, msg, "from");
		UI::get(value, msg, "value");
		if (what=="expected_times_request"){  
			expected[from]=expected_cars(from);
		} 
		else if (what=="new_expected_cars") {
			cout << "Jsem "<< name << " a dostal jsem od "<< from << " predpoklad: " << value << endl;
			//expected=0;
		}
		else {
			BaseTrafficAgent::receive(msg);
		}
	}
	
	void ds_register(const DS &ds) {
		BaseTrafficAgent::ds_register(ds);
		ds2greentimes.set_connection(rv_greentimes, ds._drv());
	}

	void from_setting(const Setting &set) {
		BaseTrafficAgent::from_setting(set);
			// load from file
		
		UI::get(sgs, set, "sgs", UI::compulsory);	
	
	}
};
UIREGISTER(GreenWaveTrafficAgent);