/*
 * lease_table.h
 *
 *  Created on: 7.8.2012
 *      Author: Petr Kramolis
 */
// This program is free software; you can redistribute it and/or
// modify it under the terms of the BUT OPEN SOURCE LICENCE
// Version 1 as published by the Brno University of Technology, Antonínská 548/1,
// 601 90, Czech Republic.
// 
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// BUT OPEN SOURCE LICENCE (BUTOSL) for more details.
// 
// You should have received a copy of the BUT OPEN SOURCE LICENCE (BUTOSL)
// along with this program; if not, write to the Brno University of Technology,
// Antonínská 548/1, 601 90, Czech Republic.


#ifndef LEASE_TABLE_H_
#define LEASE_TABLE_H_

#include <list>

#include <pthread.h>
#include <semaphore.h>

#include "ndwatch/ipv6.h"

#include "iricore_socket.h"
#include "dhcpv6.h"


extern sem_t sem;
extern sem_t sem_list;

struct timer_args;
class Lease_table_item;
class Lease_Table;
class unix_socket;
void *timer_run(void *);

struct timer_args{
	class unix_socket *usocket;
	class Lease_Table *table;
};

class Lease_table_item
{
protected:
	std::string _ident_line;
	uint64_t _timestamp;
	bool _IP; //is there IPv4 or IPv6 ident. ?
public:
	Lease_table_item(): _ident_line(""), _timestamp(0), _IP(false){}
	uint64_t timestamp() {return _timestamp;}
	void timestamp(uint64_t ts) {_timestamp = ts;}
	void append(std::string type, std::string value);
	void append(std::string ident_line);
	bool IPRecord(){return _IP;}
	string ident_line() {return _ident_line;}
	void clean(){_ident_line = ""; _timestamp = 0;}
	bool operator<(const Lease_table_item&) const;
	bool operator==(const Lease_table_item&) const;
	virtual ~Lease_table_item(){};
};

class Lease_Table
{
private:
	list<Lease_table_item> _list;
	pthread_t _timer_pth;
	struct timer_args pth_args;
public:
	Lease_Table(class unix_socket *usocket): _list(), _timer_pth()  {
		pth_args.table = this;
		pth_args.usocket = usocket;

		if (sem_init(&sem, 0, 0) == -1){
			std::cerr << "Error while creating new semaphore" << endl;
		}
		if (sem_init(&sem_list, 0, 1) == -1){
			std::cerr << "Error while creating new semaphore" << endl;
		}
		if(pthread_create(&_timer_pth,NULL, &timer_run, &pth_args) !=0) {
			std::cerr << "Error while creating new thread" << endl;
		}
	}
	void update(Lease_table_item& , unix_socket *);
	void remove(Lease_table_item& , unix_socket *);
	uint64_t check_lease(unix_socket *);
	~Lease_Table(){
		if(pthread_cancel(_timer_pth) != 0){
			std::cerr << "Error while canceling new thread" << endl;
		}
		if(pthread_join(_timer_pth , NULL) !=0) {
			std::cerr << "Error while joining new thread" << endl;
		}
	}
};

#endif /* LEASE_TABLE_H_ */
