#include <_ansi.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/fcntl.h>
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <sys/times.h>
#include <errno.h>
#include <reent.h>
#include <Npttypes.h>

#include "swi.h"
#include "natime.h"
#include "ddi.h"



#ifdef NETOS_GNU_TOOLS
static user_time_func_t user_func = NULL;
static void *user_func_data = NULL;

extern int _daylight;
extern time_t _timezone;


static int get_gmt_environ(char *env, long offset_in_sec)
{
    unsigned hour, min, sec;
    long    offset;
    int     sign = 1;


    if (offset_in_sec < 0)
        offset = -offset_in_sec; /* make it positive number */
    else
        offset = offset_in_sec;

    hour = offset/SEC_PER_MIN/MIN_PER_HOUR;

    min = (offset/SEC_PER_MIN) % MIN_PER_HOUR;
    sec = offset % SEC_PER_MIN;

    if (offset_in_sec < 0)
        hour = -hour;   /* put back the negative number */
    
    return sprintf(env, "GMT%d:%d:%d", hour, min, sec);
}
    

BOOLEAN naTimeFunctionInstall(user_time_func_t time_function, void * user_data)
{

    NA_ASSERT(time_function != NULL);
    
    user_func = time_function;
    user_func_data = user_data;
    
    return TRUE;
}

BOOLEAN naTimeZoneInstall(long std_offset_in_sec, long dst_offset_in_sec, char * dst_stzbuffer, char * dst_etzbuffer)
{
    char    environ[60];
    char    *ptr;
    int     len;
    BOOLEAN rc = TRUE;

    /* must be 30 minutes increment */
    NA_ASSERT(IS_30_MINUTES_OFFSET(std_offset_in_sec));
    NA_ASSERT(IS_30_MINUTES_OFFSET(dst_offset_in_sec));

    /* make sure no daylight saving time rule is given for one time zone */
    NA_ASSERT((int)(dst_offset_in_sec == std_offset_in_sec && dst_stzbuffer == NULL && dst_etzbuffer == NULL));
    /* make sure daylight saving time rule is given if daylight saving time is applied */
    NA_ASSERT((int)(dst_offset_in_sec != std_offset_in_sec && dst_stzbuffer != NULL && dst_etzbuffer != NULL));

    _timezone = std_offset_in_sec/SEC_PER_MIN;
    _daylight = dst_offset_in_sec/SEC_PER_MIN;

    ptr = environ;
    len = get_gmt_environ(ptr, std_offset_in_sec);
    ptr += len;
    len = get_gmt_environ(ptr, dst_offset_in_sec);

    if (dst_stzbuffer != NULL && dst_etzbuffer != NULL)
    {
        ptr += len;
        len = sprintf(ptr, ",M%s,M%s", dst_stzbuffer, dst_etzbuffer);
    }
    *(ptr+len) = '\0';

    if (setenv("TZ", environ, 1) != 0)
    {
        rc = FALSE;
    }
    return rc;
}

#endif

int
_gettimeofday (struct timeval *tv, struct timezone *tz)
{
  int rc = 0;

  NA_ASSERT(tv);

#ifdef NETOS_GNU_TOOLS
  if (user_func != NULL) 
  { /* execute user time function */
    rc = (*user_func)(&tv->tv_sec, user_func_data);
  }
  else
#endif
    tv->tv_sec = 0;

  tv->tv_usec = 0;

  /* Return fixed data for the timezone */
  if (tz != NULL)
    {
#ifdef NETOS_GNU_TOOLS
      tz->tz_minuteswest = _timezone;
      tz->tz_dsttime = _daylight;
#else
      tz->tz_minuteswest = 0;
      tz->tz_dsttime = 0;
#endif      
    }

  return rc;
}



