/*
**  OSSP tai - Time Handling
**  Copyright (c) 2002-2003 Ralf S. Engelschall <rse@engelschall.com>
**  Copyright (c) 2002-2003 The OSSP Project <http://www.ossp.org/>
**  Copyright (c) 2002-2003 Cable & Wireless Deutschland <http://www.cw.com/de/>
**
**  This file is part of OSSP tai, a time handling library
**  which can be found at http://www.ossp.org/pkg/lib/tai/.
**
**  Permission to use, copy, modify, and distribute this software for
**  any purpose with or without fee is hereby granted, provided that
**  the above copyright notice and this permission notice appear in all
**  copies.
**
**  THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
**  WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
**  MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
**  IN NO EVENT SHALL THE AUTHORS AND COPYRIGHT HOLDERS AND THEIR
**  CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
**  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
**  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
**  USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
**  ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
**  OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
**  OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
**  SUCH DAMAGE.
**
**  tai_calendar.c: calendar calculations
*/

#include "tai.h"
#include "tai_p.h"

#if 0
struct leap {
    tai_ui64_t leapsec;
} tai_tab_leapsec[] = {
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1972 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1972 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1973 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1974 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1975 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1976 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1977 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1978 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1979 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1981 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1982 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1983 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1985 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1987 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1989 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1990 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1992 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1993 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1994 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1995 Dec 31 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, /* 1997 Jun 30 23:59:60 + */
    { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }  /* 1998 Dec 31 23:59:60 + */
};
#endif

#define TAI_CAL_SUNDAY       0
#define TAI_CAL_MONDAY       1
#define TAI_CAL_TUESDAY      2
#define TAI_CAL_WEDNESDAY    3
#define TAI_CAL_THURSDAY     4
#define TAI_CAL_FRIDAY       5
#define TAI_CAL_SATURDAY     6

#define TAI_CAL_JANUARY      0
#define TAI_CAL_FEBRUARY     1
#define TAI_CAL_MARCH        2
#define TAI_CAL_APRIL        3
#define TAI_CAL_MAY          4
#define TAI_CAL_JUNE         5
#define TAI_CAL_JULY         6
#define TAI_CAL_AUGUST       7
#define TAI_CAL_SEPTEMBER    8
#define TAI_CAL_OCTOBER      9
#define TAI_CAL_NOVEMBER     10
#define TAI_CAL_DECEMBER     11

#define TAI_EPOCH "9223372036854775808" /* 2^62 / 2 (=2^63) meaning 1972-01-01 00:00:00 UTC was 1972-01-01 00:00:10 TAI */
#define TAI_EPOCH_YEAR      1970
#define TAI_EPOCH_WDAY      TAI_CAL_THURSDAY

/* the Gregorian calendar */
#define TAI_CAL_SECS_PER_MIN      60
#define TAI_CAL_MINS_PER_HOUR     60
#define TAI_CAL_HOURS_PER_DAY     24
#define TAI_CAL_DAYS_PER_WEEK     7
#define TAI_CAL_DAYS_PER_NYEAR    365
#define TAI_CAL_DAYS_PER_LYEAR    366
#define TAI_CAL_SECS_PER_HOUR     (TAI_CAL_SECS_PER_MIN * TAI_CAL_MINS_PER_HOUR)
#define TAI_CAL_SECS_PER_DAY      (TAI_CAL_SECS_PER_HOUR * TAI_CAL_HOURS_PER_DAY)
#define TAI_CAL_MONS_PER_YEAR     12

#define isleap(y) (((y) % 4) == 0 && (((y) % 100) != 0 || ((y) % 400) == 0))

tai_rc_t tai_tai2cal(tai_t *tai, int offset)
{
    tai_ui64_t secs;
    tai_ui64_t days;
    tai_ui64_t rem;
    tai_ui64_t tmp;
    tai_ui64_t tmp2;
    int lshit;

    secs = tai->sec;

    /* perform leap second correction */
    lshit = 0; /* FIXME */

    /* perform timezone offset correction */
    secs = tai_ui64_addn(secs, offset, NULL);

    /* days = secs / TAI_CAL_SECS_PER_DAY
       rem  = secs % TAI_CAL_SECS_PER_DAY */
    tmp  = tai_ui64_n2i(TAI_CAL_SECS_PER_DAY);
    days = tai_ui64_div(secs, tmp, &rem);

    /* hour = rem / TAI_CAL_SECS_PER_HOUR
       rem  = rem % TAI_CAL_SECS_PER_HOUR */
    tmp  = tai_ui64_n2i(TAI_CAL_SECS_PER_HOUR);
    tmp = tai_ui64_div(rem, tmp, &rem);
    tai->tai_hour = (int)tai_ui64_i2n(tmp);

    /* min = rem / TAI_CAL_SECS_PER_MIN
       rem = rem % TAI_CAL_SECS_PER_MIN */
    tmp  = tai_ui64_n2i(TAI_CAL_SECS_PER_MIN);
    tmp = tai_ui64_div(rem, tmp, &rem);
    tai->tai_min = (int)tai_ui64_i2n(tmp);

    /* sec = rem + lshit */
    tai->tai_sec = (int)tai_ui64_i2n(rem) + lshit;

    /* wday = (TAI_EPOCH_WDAY + days) % TAI_CAL_DAYS_PER_WEEK */
    /* FIXME: TAI is not 0 on EPOCH */
    tmp = tai_ui64_addn(days, TAI_EPOCH_WDAY, NULL);
    tmp2 = tai_ui64_n2i(TAI_CAL_DAYS_PER_WEEK);
    tai_ui64_div(tmp, tmp2, &tmp);
    tai->tai_wday = (int)tai_ui64_i2n(tmp);

    tai->tai_gmtoff = (long)offset;
    
    return TAI_OK;
}

tai_rc_t tai_cal2tai(tai_t *tai)
{
    return TAI_OK;
}

