#include <stdio.h>
#include <stdlib.h>

typedef struct
{
    int seconds;
    int minutes;
    int hours;
    int day;
    int date;
    int month;
    int year;
} RtcTime;

int rtcSecsToDate(unsigned long secs, RtcTime* tm);
int rtcDateToSecs(RtcTime* tm, unsigned long* secs);
int rtcDmyToDoy(unsigned int d, unsigned int m, unsigned int y);


/* test for tmFuncs */
int main (int argc, char *argv[])
{
    int d, m, y;
    unsigned long total_secs;
    RtcTime tm;


    printf("\ntmFunc Tester %s, %s\n\n", __DATE__, __TIME__);
    
    
    if ( argc < 3 )
    {
        printf("usage: %s [d] [m] [y]\n", argv[0]);
        return -1;
    }

    d = atoi(argv[1]);
    m = atoi(argv[2]);
    y = atoi(argv[3]);
    

    printf("rtcDmyToDoy(%d, %d, %d) = %d\n", d, m, y, rtcDmyToDoy(d, m, y));

    printf("-------------- test of rtcDateToSecs(...) -------------- \n");

    
    tm.seconds = 1;
    tm.minutes = 1;
    tm.hours = 1;
    tm.day = 1;
    tm.date = d;
    tm.month = m;
    tm.year = y;

    rtcDateToSecs(&tm, &total_secs);

    printf("total_seconds = %lu\n", total_secs);

    return 0;
}

int rtcSecsToDate(unsigned long secs, RtcTime* tm)
{
    /* This func is designed to populate an RtcTime struct based on the 
    seconds since 00:00:00 1/1/2000. I'm using this as a custom epoch to 
    match the DS3234 RTC. */ 

    /* range check from 0 to about 3.16 e9 seconds ( ~100 years ) */

    /* div by year seconds and inc year */

    /* now the seconds are less than a year so start decrementing by month 
    chunks and be mindful of leaps years */

    /* div by day seconds for partial month */

    /* div by hour seconds */

    /* div by minute seconds */

    /* the remainder is seconds */
    
    /* return the total */
    return 0;
}

int rtcDateToSecs(RtcTime* tm, unsigned long* secs)
{
    int i;
    long total_days = 0;

    /* This func is designed to return the seconds that have elapsed 
    between 00:00:00 1/1/2000 and the time contained in the RtcTime 
    struct.  I'm using this as a custom epoch to match the DS3234 RTC. */ 

    /* check the seconds */
    if ( (tm->seconds < 0) || (tm->seconds > 59) )
        return -1;
    
    /* check the minutes */
    if ( (tm->minutes < 0) || (tm->minutes > 59) )
        return -1;
    
    /* check the hours */
    if ( (tm->hours < 0) || (tm->hours > 23) )
        return -1;
    
    /* check the day */
    if ( (tm->date < 1) || (tm->date > 31) )
        return -1;
    
    /* check the month */
    if ( (tm->month < 1) || (tm->month > 12) )
        return -1;
    
    /* check the year */
    if ( (tm->year < 2000) || (tm->year > 2099) )
        return -1;


    if ( tm->year > 2000)
    {
        for (i = 0; i < (tm->year - 2000); ++i)
        {
            if ( (2000 + i) % 4 )
            {
                total_days += 365;
printf("%d is not a leap year +365\n", (2000 + i));
            }
            else
            {
                total_days += 366;
printf("%d is a leap year +366\n", (2000 + i));
            }
        }
printf("total days from 2000 through %d is %ld\n", (tm->year - 1), total_days);
    }

    total_days += (rtcDmyToDoy(tm->date, tm->month, tm->year) - 1);

printf("total days from 2000 to %d/%d/%d is %ld\n", 
       tm->month, tm->date, tm->year, total_days);

    *secs = total_days * 86400;

    *secs += tm->hours * 3600;

    *secs += tm->minutes * 60;

    *secs += tm->seconds;
    
    /* return the total */
    return 1;
}

int rtcDmyToDoy(unsigned int d, unsigned int m, unsigned int y)
{
    int doy;

    /* Some simple range checks.  This doesn't catch all the bogus dates, but 
    it gets most.  This function is designed to work from 2000 - 2099 to match 
    the DS3234 RTC and to avoid all the 100 year/400 year leap year stuff */
    
    /* check the day */
    if ( (d < 1) || (d > 31) )
        return -1;
    
    /* check the month */
    if ( (m < 1) || (m > 12) )
        return -1;
    
    /* check the year */
    if ( (y < 2000) || (y > 2099) )
        return -1;

    /* get the cumulative days for any past months */
    switch ( m )
    {
        case 1: doy = 0; break;
        case 2: doy = 31; break;
        case 3: doy = 59; break;
        case 4: doy = 90; break;
        case 5: doy = 120; break;
        case 6: doy = 151; break;
        case 7: doy = 181; break;
        case 8: doy = 212; break;
        case 9: doy = 243; break;
        case 10: doy = 273; break;
        case 11: doy = 304; break;
        case 12: doy = 334; break;
        default: break;
    }

    /* add all the days for the current month */
    doy += d;

    /* add a day if it's a leap year and you're past February */
    if ( ((y % 4) == 0) && (m > 2) )
        doy += 1;

    /* return the total */
    return doy;
}

