#ifndef CALENDAR_H_
#define CALENDAR_H_
// projektlokala headerfiler
#include "kattistime.h"
#include "gregorian.h"
#include "event.h"
// STL headerfiler
#include <iostream>
#include <assert.h>
#include <ctime>
#include <vector>
#include <algorithm>
namespace lab2
{
template<class T>
class Calendar
{
typedef typename std::vector<Event<T> *> EVector;
typedef typename EVector::iterator EVectorIt;
public:
Calendar();
Calendar(const T &);
~Calendar();
Calendar(const Calendar &);
Calendar<T> & operator=(const Calendar<T> &);
bool set_date(int year, int month, int day);
bool add_event(std::string event);
bool add_event(std::string event, int day);
bool add_event(std::string event, int day, int month);
bool add_event(std::string event, int day, int month, int year);
bool remove_event(std::string event);
bool remove_event(std::string event, int day);
bool remove_event(std::string event, int day, int month);
bool remove_event(std::string event, int day, int month, int year);
EVector events;
T * date;
friend std::ostream & operator<<(std::ostream & out, const Calendar & cal)
{
for (unsigned int i = 0; i < cal.events.size(); i++)
{
if (*(cal.events[i]->d) >= *(cal.date))
{
out << *(cal.events[i]->d) << " : " << cal.events[i]->happening
<< "\n";
}
}
return out;
}
};
template<class T> Calendar<T>::Calendar()
{
date = new T();
}
template<class T> Calendar<T>::Calendar(const T & in) :
date(in)
{
}
template<class T> Calendar<T>::Calendar(const Calendar<T> & calendar)
{
date = new T(calendar.date);
for (unsigned int i = 0; i < calendar.events.size(); i++)
{
Event<T> * key = new Event<T>(*calendar.events[i]);
events.push_back(key);
}
}
template<class T> Calendar<T>& Calendar<T>::operator =(const Calendar<T> & calendar)
{
if (this == &calendar){
return *this;
}
delete date;
date = new T(calendar.date);
for (unsigned int i = 0; i < events.size(); i++)
{
delete events[i];
}
events.empty();
for (unsigned int i = 0; i < calendar.events.size(); i++)
{
Event<T> * key = new Event<T>(*calendar.events[i]);
events.push_back(key);
}
return *this;
}
template<class T> Calendar<T>::~Calendar()
{
delete &date;
for (unsigned int i = 0; i < events.size(); i++)
{
delete events[i];
}
events.empty();
}
template<class T> bool Calendar<T>::set_date(int year, int month, int day)
{
try
{
T * t = new T(year, month, day);
date = t;
} catch (std::out_of_range)
{
return false;
}
return true;
}
template<class T> bool Calendar<T>::add_event(std::string happening)
{
return add_event(happening, date->day(), date->month(), date->year());
}
template<class T> bool Calendar<T>::add_event(std::string happening, int day)
{
return add_event(happening, day, date->month(), date->year());
}
template<class T> bool Calendar<T>::add_event(std::string happening, int day,
int month)
{
return add_event(happening, day, month, date->year());
}
template<class T> bool Calendar<T>::add_event(std::string happening, int day,
int month, int year)
{
Event<T> * event = new Event<T>(happening, day, month, year);
EVectorIt left, mid, right;
left = events.begin();
right = events.end();
int count = distance(left, right);
while (0 < count)
{ // divide and conquer to find lowest bound (ei first element >= key).
int count2 = count / 2;
mid = left;
advance(mid, count2);
if (*(*(mid)) < *event)
{ // try left half
left = ++mid;
count -= count2 + 1;
}
else
{
count = count2;
}
}
// the specs says that list should be ordered by date first and insert order next.
// this means we can't just sort and then add because we need walk over all with same dates and check for comparison and then add.
// left points to first element not less than key (e.i same date)
if (left != right)
{ // if we are not at the end
while (*(*(*left)).d == *(*event).d)
{ // go over all with the same date
if ((*(*left)) == *event)
{ // and check for identical key
return false; // if same key is found, return false.
}
left++;
if (left == right)
{ // if we came to the end
events.push_back(event); // add and return
return true;
}
}
events.insert(left, event); // we have walked over all elements with same date and none were same as key and we are not at the end.
return true;
}
else
{ // left is equals right, we are at the end.
events.push_back(event);
return true;
}
}
template<class T> bool Calendar<T>::remove_event(std::string happening)
{
return remove_event(happening, date->day(), date->month(), date->year());
}
template<class T> bool Calendar<T>::remove_event(std::string happening, int day)
{
return remove_event(happening, day, date->month(), date->year());
}
template<class T> bool Calendar<T>::remove_event(std::string happening, int day,
int month)
{
return remove_event(happening, day, month, date->year());
}
template<class T> bool Calendar<T>::remove_event(std::string happening, int day,
int month, int year)
{
Event<T> event(happening, day, month, year);
EVectorIt left, mid, right;
left = events.begin();
right = events.end();
int count = distance(left, right);
while (0 < count)
{ // divide and conquer, find half that contains answer
int count2 = count / 2;
mid = left;
advance(mid, count2);
if (*(*(mid)) < event)
{ // try left half
left = ++mid;
count -= count2 + 1;
}
else if (*(*(mid)) == event)
{
events.erase(mid);
return true;
}
else
{
count = count2;
}
}
return false;
}
}
#endif