#ifndef CALENDAR_LIB_H
#define CALENDAR_LIB_H

#include <time.h>

#define MAX_CALENDAR_TIMEZONE_CHANGES 3
#define MAX_CALENDAR_TIMEZONE_CHANGES2 100

typedef struct {
	int nth; /* 1=first 2=second 3=third 4+ =last */
	int weekday; /* 0=Sun */
	int month_num; /* 0=Jan */
	int at_minutes; /* seconds past midnight */
	int change_by;

	/*
	e.g. 3rd Sunday of March, -3600
	*/
} DaylightSavingsChangeRule;

typedef struct {
	int offset;
	time_t change_at[MAX_CALENDAR_TIMEZONE_CHANGES];
	int change_by[MAX_CALENDAR_TIMEZONE_CHANGES];
	DaylightSavingsChangeRule ds_rules[2];
	int calculated_other_changes;
	time_t past_changes_at[MAX_CALENDAR_TIMEZONE_CHANGES2];
	int past_changes_by[MAX_CALENDAR_TIMEZONE_CHANGES2];
	time_t future_changes_at[MAX_CALENDAR_TIMEZONE_CHANGES2];
	int future_changes_by[MAX_CALENDAR_TIMEZONE_CHANGES2];
} CalendarTimeZone;

int calendar_lib_offset_at(time_t t, CalendarTimeZone *user_tz);
int calendar_lib_user_offset_at(time_t t, CalendarTimeZone *user_tz);
struct tm *calendar_lib_localtime(time_t *t, struct tm *tt, CalendarTimeZone *user_tz);
time_t calendar_lib_mktime(struct tm *t, CalendarTimeZone *user_tz);
int calendar_lib_tm_to_day(struct tm *t, CalendarTimeZone *user_tz);
struct tm *calendar_lib_localtime_for_offset(time_t t, struct tm *tt, int offset_from_gmt);

#ifndef CALENDAR_EVENT_DEFINED
#define CALENDAR_EVENT_DEFINED 1




#ifdef IS_SURGEPLUS_CLIENT
#include "GuiUtilities.h"
#include "aEventPanel.h"
#endif

#define CALENDAR_LIB_EVENT_TYPE_SCHEDULED 0
#define CALENDAR_LIB_EVENT_TYPE_BIRTHDAY 1



typedef struct {
	time_t event_start; // Date & time which event starts from
	int repeat_type; // 0=doesn't repeat. 1=Standard repeat every x seconds. 2=repeat date (like 4th of every month)

	/* Standard repeating event fields: */
	int repeat_interval; // Event repeats every this many seconds. (if this value is greater than 1 day (60*60*24) then it must be a multiple of a day. if multiple of a day, then server should handle daylight saving adjustments)
	//int ExcludeDayMask[7];	// Do not generate event if it occurs on given day of week (0=Sunday .. 6=Saturday).
	int alternative_day_mask[7]; // 0=Occurs on this day as normal. 1=Does not occur. 2=Occurs at alternative time
	int alternative_day_time[7]; // seconds past midnight.
	int alternative_day_duration[7]; // duration in seconds
	int event_type; //0=Scheduled. 1=Birthday.

	//int SecondMin,SecondMax; // Only generate event if seconds past midnight is between SecondMin and SecondMax (e.g. for a hourly repeating message, might be set to only repeat between 9am and 5pm)
	time_t event_last_repeat_at; // if >0, then specifies the Date & time that event no longer repeats after.

	/* Special repeating event fields: */
	int repeat_day_type; //0=Sunday .. 6=Saturday, 7=week-day, 8=weekend-day.   9=day,
	int repeat_day_num; //1..31 or 99(=last) (e.g. repeat_day_type=0, repeat_day_num==2 means every 2nd sunday. repeat_day_type=9 repeat_day_num=12 means 12th day)
	int repeat_on_month; // If >0 then repeats on this month (1=Jan 12=Dec)
	int repeat_every_month; // if >0 then repeats every this many months

#ifdef IS_SURGEPLUS_CLIENT
	APairs pairs;
	EventID id;
	AList<time_t> repeat_exceptions;
	AList<int> repeat_exceptions_time;
	AList<int> repeat_exceptions_duration;
#define repeat_exceptions_length repeat_exceptions.Length
#define repeat_exceptions_time_length repeat_exceptions_time.Length
#define repeat_exceptions_duration_length repeat_exceptions_duration.Length
#else
	int id;
	time_t *repeat_exceptions;/* Event does not occur at these times.*/
	int repeat_exceptions_length;

	int *repeat_exceptions_time;  /* 0=not occurs, otherwise seconds past midnight+1.*/
	int repeat_exceptions_time_length;

	int *repeat_exceptions_duration; /* / duration in seconds. Only applies if repeat_exceptions_time is non-zero. */
	int repeat_exceptions_duration_length;
#endif


	struct tm event_start_tm;
	struct tm event_end_tm;

/*
	int sms_offset;	// If >0 then also sends a pre-event sms this many seconds before the event.

	int email_offset; // If >0 then also sends a pre-event sms this many seconds before the event.
*/

	/*
	Examples:
	1) Repeat every weekday
	repeat_type=1
	repeat_interval=60*60*24
	DayMask=[1,0,0,0,0,0,1]
	All other fields are 0.

	2) Repeat every 4th November
	repeat_type=2
	repeat_month=11
	repeat_day_num=4
	repeat_day_type=9

	3) Repeat on 3rd Monday of every October
	repeat_type=2
	repeat_month=10
	repeat_day_num=3
	repeat_day_type=1

	4) Repeat on last Sunday of every 2nd month
	repeat_type=2
	repeat_months=2
	repeat_day_type=0
	repeat_day_num=99


	*/

#ifdef IS_SURGEPLUS_CLIENT
	bool save_on_server_failed;
	int duration;

	AnsiString name;
/*	AnsiString data;*/
	//AnsiString user; // USer name that event belongs to, or "" if self.
	int server_change_value; // 0 When edited locally, but not saved on server. set to strictly increasing value when sucessfully saved on server.

	AList<TDateTime> repeat_exceptions_dt;
	AList<struct tm> repeat_exceptions_tm;

/*
	AnsiString sms_to;
	AnsiString sms_message;
	AnsiString email_to;
	AnsiString email_subject;
	AnsiString email_message;
*/

	AnsiString time_text;
	AnsiString time_text_short;
	TDateTime time;
	TDateTime end_time;
	TDateTime end_date;
	TDateTime next_occurance;
	TDateTime previous_occurance;
	EventPanel *panel;
	int pleft,ptop,pwidth,pheight;
	IStaticText *text;
	int panel_half_width;
	time_t this_event_start;
	time_t this_event_end;

	bool deletion_flag;
/*
Must add any new values into calendareventstuctclear function
*/	
#endif




} CalendarEvent;

#endif

int calendar_lib_is_nth_x_of_month(int n, int x, int day, int month, int year);
int calendar_lib_is_nth_weekday_of_month(int day, int month, int year, int n, int backwards_search, int weekend_search);
int calendar_lib_day_of_week(int year, int month, int day);
int calendar_lib_days_in_month(int month, int year);
int calendar_lib_is_leap_year(int year);
time_t calendar_lib_event_get_next_occurance(CalendarEvent e, time_t now_in_user_time, int find_previous, CalendarTimeZone *user_tz);
void calendar_lib_inc_days(int *day, int *month, int *year, int ddays);
int calendar_lib_tm_same_dayp(struct tm *t1, struct tm *t2);


int calendar_lib_get_hour(char *rec, int *hour, int *min, int *sec);
int calendar_lib_get_zone(char *rec); /* return time zone offset in seconds, GMT = 0 */
int calendar_lib_tzone_find(char *s);
time_t calendar_lib_parse_date(char *rec);
int calendar_lib_extract_zone(char *date); /* return time zone offset in seconds, GMT = 0 */
time_t calendar_lib_adjust_tm_for_offset(time_t a, int offset);



#endif
