#include <stdio.h>
#include <sys/types.h>
#include "greg.h"
#include "error.h"

/* greg.c gregorian calendar module for hebrew calendar program
   By Danny Sadinoff
   (C) 1992

*/

char * eMonths[] = { 
  "January","February","March","April","May","June","July",
  "August","September","October","November","December"
  };
		      
int MonthLengths[][12] ={ 
  {31,28,31,30,31,30,31,31,30,31,30,31},
  {31,29,31,30,31,30,31,31,30,31,30,31}
};

char * DayNames[] = {
  "Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"
  };

char * ShortDayNames[] = {
  "Sun","Mon","Tue","Wed","Thu","Fri","Sat"
  };

static void checkRange (dt,routine)
date_t dt;
char * routine;
{
  if ((dt.mm > 13)||(dt.dd > 31) || (dt.yy > 7000) || 
      (dt.mm <0)  ||(dt.dd <0  ) || (dt.yy < -7000))
    die("Date out of range from routine %s.",routine);
}

static long int daysSinceOrigin (dt)
date_t dt;
{
  int m,y;
  long int days = 0L;

  checkRange(dt,"daysSinceOrigin");

  for (y =1; y < dt.yy; y++)
    days += DAYS_IN(y);
  y = dt.yy;
  for (m= JAN; m < dt.mm; m++)
    days += MonthLengths[LEAP(y)][m];
  days += dt.dd -1;
  return days;
}

int diffDays(d1,d2)
date_t d1, d2;
{
  return (int) (daysSinceOrigin(d1) - daysSinceOrigin(d2));
}

int exceeds (d1,d2)
date_t d1, d2;
{
  if (d1.yy > d2.yy)
    return 1;
  else if (d1.yy < d2.yy)
    return 0;
  else if (d1.mm > d2.mm)
    return 1;
  else if (d1.mm < d2.mm)
    return 0;
  else if (d1.dd > d2.dd)
    return 1;
  else return 0;
}

void decDate (dt,n) /* decrements dt by n days */
date_t *dt;
int n;
{
/*under construction*/
/*  while (n > 365) {
    n -= DAYS_IN(dt->yy -1);
    dt ->yy--;
  }


  if ((dt->mm == FEB) && (dt->dd == 29) && !LEAP(dt->yy))
    dt->dd--;
*/
  
  while (n--) 
    if (dt->dd ==1) {
      if (dt->mm == JAN) {
	dt->yy--;
	dt->mm = DEC;
	dt->dd = 31;
      }
      else {
	dt->mm--;
	dt->dd = MonthLengths[LEAP(dt->yy)][dt->mm];
      }
    }
    else dt->dd--;
}

void incDate (dt,n)   /* increments dt by n days */
date_t *dt;
int n;
{
/*  while (n > 365) {
    n -= DAYS_IN(dt->yy);
    dt->yy++;
  }

  if ((dt->mm == FEB) && (dt->dd == 29) && !LEAP(dt->yy) ) {
    dt-> mm = MAR;
    dt-> dd = 1;
  }
*/
  while (n--) 
   if ((dt->dd + 1) > MonthLengths[LEAP(dt->yy)][dt->mm]) 
     if (dt->mm == DEC) {
       dt->yy++;
       dt->mm = JAN;
       dt->dd = 1;
     }
     else {
       dt->mm++;
       dt->dd =1;
     }
   else 
     dt->dd ++;
}

int dayOfWeek(d1)  /* sunday = 0 */
date_t d1;
{
  return (int) ((daysSinceOrigin(d1) + 1) % 7 ) ;
}

void setDate (d) 
date_t *d;
{
  time_t secs;
  struct tm *loctm;

  secs = time(NULL);
  loctm = localtime(&secs);
  d->yy = 1900 + loctm->tm_year;
  d->mm = loctm->tm_mon;
  d->dd = loctm->tm_mday;
}


