/*  wmbday
 *  Copyright (C) 2003-2005 astratis <steffen@x-berg.de>
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public Licensse as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  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
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 */

#include <time.h>


/* Return Values: 0 if dates are equal, -1 if first date earlier, 1 if first date later */
int compare_dates(int day1, int month1, int day2, int month2) {
  if(day1 == day2 && month1 == month2)
    return 0;

  if(month1 < month2)
    return -1;
  if(month1 > month2)
    return 1;

  if(day1 < day2)
    return -1;
  if(day1 > day2)
    return 1;

  return 0;
}


/* returns number of days between two dates */
int days_between_dates(int day1, int month1, int day2, int month2, int year) {
  struct tm now;
  struct tm future;
  time_t unix_now;
  time_t unix_future;
  int rollover = 0;

  if(compare_dates(day1, month1, day2, month2) == 1) /* if birthday date is "before" now (seen without year) */
    rollover = 1;

  now.tm_mon = month1 - 1;
  now.tm_mday = day1;
  now.tm_hour = now.tm_min = now.tm_sec = 0;
  now.tm_year = year - 1900;
  now.tm_isdst = -1; /* no DST-adjustments desired */

  future.tm_mon = month2 - 1;
  future.tm_mday = day2;
  future.tm_hour = future.tm_min = future.tm_sec = 0;
  future.tm_year = (year - 1900) + rollover;
  future.tm_isdst = -1; /* no DST-adjustments desired */

  unix_now = mktime(&now);
  unix_future = mktime(&future);

  return (unix_future - unix_now) / 86400;
}


/* checks for valid date */
int is_date(int day, int month, int year) {
  time_t tnow;
  struct tm *now;
  int maxday = 28;

  tnow = time(NULL);
  now = localtime(&tnow);

  /* check month range */
  if(month < 1 || month > 12)
    return 0;

  /* check day range and consider leap years */
  if(month == 2) {
    if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0)
      ++maxday;
  }
  else if(month == 4 || month == 6 || month == 9 || month == 11)
    maxday = 30;
  else
    maxday = 31;

  if(day < 1 || day > maxday)
    return 0;

  /* check that date is not in the future */
  if(year > now->tm_year + 1900)
    return 0;

  if(year == now->tm_year + 1900) {
    if(compare_dates(day, month, now->tm_mday, now->tm_mon + 1) <=0) {
      return 1;
    }
    else {
      return 0;
    }
  }

  return 1;
}
