/*
   File:        dates.h
   Author:      A. Moore
   Created:     Tue Jul 23 15:42:17 EDT 2002
   Description: Header for Date processing

   Copyright 2002, The Auton Lab, CMU
*/
/* THIS FILE IS OBSOLETE. ALL OF ITS FUNCTIONALITY
 * NOW RESIDES IN UTILS/AM_TIME.H */

#ifdef PAIN
#ifndef DATES_H
#define DATES_H
#include "genarray.h"

/* A date is a data structure to represent an onion.

   No...actually it represents a date.

   You can parse dates, and reason about number of days between dates
   and increment dates by given numbers of days. It's all efficient (all
   constant-time operations).
*/

typedef struct date
{
  int year;
  int month;
  int day;
} date;

void free_date(date *x);

void fprintf_date(FILE *s,char *m1,date *x,char *m2);

void pdate(date *x);

date *mk_copy_date(date *old);

/* Returns TRUE if and only "year" is a leapyear */
bool is_leap_year(int year);

/* Input: 1 <= month <= 12.
   Output: Number of days in month in given year. */
int month_to_length(int year,int month);

/* Input: 1 <= month <= 12.
   Output: Pointer to static string (should not be freed) 
           representing month. */
char *month_to_name(int month);

/* Input: 1800 <= year <= MAX_YEAR, 1 <= month <= 12,
          1 <= day <= days in month

   Output: Representation of date. */
date *mk_date(int year,int month,int day);

/* Accessor */
int date_year(date *d);

/* Accessor */
int date_month(date *d);

/* Accessor */
int date_day(date *d);

/* a daycode is an integer representing a given date.

   Tomorrow is always represented by a daycode of one greater than today,
   thus given two dates, the number of days between them equals the
   difference of their daycodes. */
int date_to_daycode(date *d);

/* Returns number of days from a until b.
   0 if same date
   > 0 if b later than a
   < 0 if b earlier than a
*/
int days_between(date *a,date *b);

/* day_of_week is a number such that 0 <= day_of_week <= 6 with

   0 represents Monday
   1 represents Tuesday
      :
   5 represents Saturday
   6 represents Sunday

   Input: day_of_week
   Output: Static pointer to string that names day_of_week
*/
char *day_of_week_to_name(int day_of_week);

/* MAKES and returns a string in "MMM-DD-YYYY" where MMM is the three-letter
   text name of the month */
char *mk_string_from_date(date *d);

/* Returns the month (1 <= month <= 12) represented by the string.
   Just looks at the first three chars of string, thus

     "decadent" will return 12 (= december)

     Returns -1 if string matches no month */
int name_to_month(char *s);


/* Parses a date. A date may be 1,2 or 3 components separated by 
   "ignore characters" where "ignore characters" are :-/ and space

   Figures out which of the components is the year by looking for 
   something between 1800 and max_year

   Then assume the earlier of the two remaining components is the month
   (thus failing to parse UK format dates).

   And the later of the two components is day of month.

   Can handle month being given by name (in any case) using the same
   rules as name_to_month() above.

   It DOES handle sates of the form DD-MMM-YYYY successfully, even those
   are UK style, but only if MMM is text format.

   If there's a parse error then this function returns NULL, and MAKES
   and RETURNS an error message (which must later be free_string()'d)
   in *r_errmess.

   If happy, returns date d, and sets *r_errmess to NULL.
*/
date *mk_date_from_string(char *s,char **r_errmess);

/* Returns 0 for monday, 1 for tuesday, ... 5 for saturday, 6 for sunday */
int daycode_to_day_of_week(int daycode);

/* Returns 0 for monday, 1 for tuesday, ... 5 for saturday, 6 for sunday */
int date_to_day_of_week(date *d);

/* Same as mk_date_from_string above, except my_error()'s if parse error */
date *mk_date_from_string_simple(char *s);

/* Makes the date d such that date_to_daycode(d) = daycode */
date *mk_date_from_daycode(int daycode);

/* MAKES and returns a string in "MMM-DD-YYYY" where MMM is the three-letter
   text name of the month */
char *mk_string_from_daycode(int daycode);

/* Change d so that it is "num_days" later.
   If num_days is -ve, moves to appropriate earlier date. */
void increment_date(date *d,int num_days);

/* If parse error... returns -1 and MAKES and stores message in *r_errmess */
/* If OK sets *r_errmess to NULL */
int string_to_daycode(char *string,char **r_errmess);

/* If parse error... returns -1 and MAKES and stores message in *r_errmess */
/* If OK sets *r_errmess to NULL */
int daycode_from_args(char *key,int argc,char *argv[],int default_daycode,
		      char **r_errmess);

typedef struct dates
{
  generic_array *genarr;
} dates;

/************ Begin dates *************/

dates *mk_empty_dates(void);

void add_to_dates(dates *array,date *element);

void add_pointer_to_dates(dates *array,date *element);

int dates_size(dates *array);

date *dates_ref(dates *array,int index);
  
void fprintf_dates(FILE *s,char *m1,dates *array,char *m2);

void pdates(dates *array);

void free_dates(dates *array);

dates *mk_copy_dates(dates *array);

void dates_set(dates *array,int index,date *d);

void dates_remove(dates *array,int index);

/************** End dates ******************/

#endif /* #ifndef DATES_H */
#endif /* PAIN */
