#include<iostream>	
#include <time.h>
using namespace std;

#include "cData.h"

///////////////////////////////////////////////////////
// public methods
cData::cData()
{
	time_t tempo;
	struct tm *hoje;
//retorna o nº de segundos desde as 00:00:00 de 1 de Janeiro de 1970
	time(&tempo); 
	hoje=localtime(&tempo);
	this->setData(hoje->tm_mday,hoje->tm_mon+1,hoje->tm_year+1900);
}
cData::cData(int d,int m,int a)
{
	this->setData(d,m,a);
}
cData::cData(const cData & dt)
{
	operator=(dt);
}
cData::~cData()
{
}
int cData::getDia()const
{
	return this->m_iDia;
}
int cData::getMes()const
{
	return this->m_iMes;
}
int cData::getAno()const
{
	return this->m_iAno;
}
void cData::setData(int d,int m,int a)
{
	if(isDataValida(d,m,a)){
		this->m_iDia=d;
		this->m_iMes=m;
		this->m_iAno=a;
	}
	else{
		cout<<"Erro: data invalida"<<endl;
		this->m_iDia=1;
		this->m_iMes=1;
		this->m_iAno=0;
	}
}
cData & cData::operator = (const cData &dt)
{
	if(this==&dt)
		return *this;
	this->m_iDia=dt.getDia();
	this->m_iMes=dt.getMes();
	this->m_iAno=dt.getAno();

	return *this;
}
bool cData::operator == (const cData & dt)
{
	return ((this->m_iDia==dt.getDia() && this->m_iMes==dt.getMes() &&	this->m_iAno==dt.getAno()) ? true : false);
}
cData & cData::operator ++ ()
{
	if(this->m_iDia <this->getDiasMes(this->m_iMes,this->m_iAno)-1){
		this->m_iDia++;
	}
	else{
		
		if(this->m_iMes<12){
			this->m_iMes++;		
			this->m_iDia=this->getDiasMes(this->m_iMes,this->m_iAno);
		}
		else{
			this->m_iMes=1;
			this->m_iAno++;
			this->m_iDia=this->getDiasMes(this->m_iMes,this->m_iAno);
		}
		
	}
	return *this;
}
cData & cData::operator -- ()
{
	if(this->m_iDia >1){
		this->m_iDia--;
	}
	else{
		if(this->m_iMes>1){
			this->m_iMes--;	
			this->m_iDia=this->getDiasMes(this->m_iMes,this->m_iAno);
		}
		else{
			this->m_iMes=12;
			this->m_iAno--;
			this->m_iDia=this->getDiasMes(this->m_iMes,this->m_iAno);
		}
	}
	return *this;
}
void cData::getDiaSemana(char * ds)
{
	int d=0;
	for(int i=1; i<this->m_iAno; i++)
		if(this->isAnoBissexto(i))
			d+=2;		//se ano bissexto salta dois dias
		else
			d++;		//senão salta só um dia

	// d é agora o dia da semana do primeiro dia do ano
	// falta somar o nº de dias que já passaram desde o inicio do ano
	d+=this->getNumDiasAno();
	this->getDiaSemana((d%7)+1,ds);
	
}
int cData::anosCompletos(const cData &dt)
{ 
	if(this->m_iAno>dt.getAno()){
		if(this->m_iMes>dt.getMes() || (this->m_iMes==dt.getMes() &&this->m_iDia>dt.getDia())) 
			return (this->m_iAno-dt.getAno());		
		return (this->m_iAno-dt.getAno()-1);
	}
	if(this->m_iAno<dt.getAno()){
		if(this->m_iMes<dt.getMes() || (this->m_iMes==dt.getMes() &&this->m_iDia<dt.getDia())) 
			return (dt.getAno()-this->m_iAno);		
		return (dt.getAno()-this->m_iAno-1);
	}
	return 0;
}
///////////////////////////////////////////////////////
// private methods
bool cData::isAnoBissexto(int ano)const
{
	return (((ano%400==0) || (ano%4==0 && ano%100!=0)) ? true : false);
}
bool cData::isDataValida(int d, int m, int a)const
{
	if(d > 0 && m > 0 && a>=0){
		switch(m){
			case 1:	case 3:	case 5:	case 7:	case 8:	case 10:case 12:
				if(d>0 && d<=31)
					return true;
				break;
			case 4:	case 6:	case 9:	case 11:
				if(d>0 && d<=30)
					return true;
				break;
			case 2:
				if(d>0 && d<=28)
				   return true;

				if(d==29 && isAnoBissexto(a))
					return true;
				break;
			default:
				cout<<"Erro: mes errado"<<endl;
		}
	}
	return false;
}
int cData::getDiasMes(int m, int a)const
{
	int d=31;
	switch(m){
		case 4:	case 6:	case 9:	case 11:
			d=30;
			break;
		case 2:
			d=28;
			if(isAnoBissexto(a))
				d=29;
			break;
		}
	return d;
}
void cData::getDiaSemana(int i, char *ds)const
{
	ds[0]='\0';
	switch(i){
		case 1: strcpy(ds,"Domingo");break;
		case 2:	strcpy(ds,"Segunda");break;
		case 3:	strcpy(ds,"Terça");break;
		case 4:	strcpy(ds,"Quarta");break;
		case 5:	strcpy(ds,"Quinta");break;
		case 6:	strcpy(ds,"Sexta");break;
		case 7:	strcpy(ds,"Sabado");break;
	}
}
int cData::getNumDiasAno()const
{
	int dias=this->m_iDia;
	for(int i=1;i<this->m_iMes;i++)
		dias+=getDiasMes(i, this->m_iAno);
	return dias;
}
void cData::ler(istream & in)
{
	int d, m, a;
	cout<<"Digite o dia: ";
	in>>d;
	cout<<"Digite o mes: ";
	in>>m;
	cout<<"Digite o ano: ";
	in>>a;
	this->setData(d,m,a);
}
void cData::escreve(ostream &out)
{
	out<<this->getDia()<<"/"<<this->getMes()<<"/"<<this->getAno()<<endl;
}
///////////////////////////////////////////////////////
// friend function
ostream & operator << (ostream &out, cData & dt)
{
	dt.escreve(out);
	return out;
}
istream & operator >> (istream & in, cData & dt)
{
	dt.ler(in);
	return in;
}