#ifndef CLICK_MINSTREL_HH
#define CLICK_MINSTREL_HH
#include <click/element.hh>
#include <click/dequeue.hh>
#include <click/etheraddress.hh>
#include <click/bighashmap.hh>
#include <click/glue.hh>
#include <click/timer.hh>
#include <elements/wifi/bitrate.hh>
CLICK_DECLS

/*
 * =c
 * Minstrel([, I<KEYWORDS>])
 * =s Wifi
 * Minstrel wireless bit-rate selection algorithm
 * =a SetTXRate, FilterTX
 */

class Minstrel : public Element { public:

	Minstrel();
	~Minstrel();

	const char *class_name() const		{ return "Minstrel"; }
	const char *port_count() const		{ return "2/0-2"; }
	const char *processing() const		{ return "ah/a"; }
	const char *flow_code() const			{ return "#/#"; }

	int initialize(ErrorHandler *);
	int configure(Vector<String> &, ErrorHandler *);
	void run_timer(Timer *);

	void push (int, Packet *);
	Packet *pull(int);

	/* handler stuff */
	void add_handlers();
	String print_rates();

	void assign_rate(Packet *);
	void process_feedback(Packet *);

private:

	struct DstInfo {
	public:
		EtherAddress _eth;
		Vector<int> _rates;
		Vector<int> _this_success;
		Vector<int> _this_attemps;
		Vector<int> _tot_success;
		Vector<int> _tot_attemps;
		DstInfo() {
		}
		DstInfo(EtherAddress eth, Vector<int> rates) {
			_eth = eth;
			_rates = rates;
			_this_success = Vector<int>(_rates.size(), 0);
			_this_attemps = Vector<int>(_rates.size(), 0);
			_tot_success = Vector<int>(_rates.size(), 0);
			_tot_attemps = Vector<int>(_rates.size(), 0);
		}
		int rate_index(int rate) {
			int ndx = 0;
			for (int x = 0; x < _rates.size(); x++) {
				if (rate == _rates[x]) {
					ndx = x;
					break;
				}
			}
			return (ndx == _rates.size()) ? -1 : ndx;
		}
		void add_result(int rate, int tries, int success) {
		}
	};

	typedef HashMap<EtherAddress, DstInfo> NeighborTable;
	typedef NeighborTable::const_iterator NeighborIter;

	NeighborTable _neighbors;
	AvailableRates *_rtable;
	Timer _timer;

	bool _active;
	unsigned _offset;
	unsigned _rate;
	unsigned _tries;
	unsigned _period;
	bool _debug;

	static int write_handler(const String &, Element *, void *, ErrorHandler *);
	static String read_handler(Element *, void *);

};

CLICK_ENDDECLS
#endif

