#include <assert.h>
#include <sys/time.h>
#include <time.h>
#if __VMS
#include <sys/timeb.h>
#endif
#include "myc_fortran.h"
#include "myc_time.h"


static time_t my_base=0;

void initBase(void) {
  struct tm tim;
  time_t now;

  time(&now);
  tim = *localtime(&now);
  tim.tm_year = MYC_TIME_BASE / 10000 - 1900;
  tim.tm_mon  = (MYC_TIME_BASE % 10000) / 100 - 1;
  tim.tm_mday = MYC_TIME_BASE % 100;
  tim.tm_hour = 12;
  tim.tm_min  = 0;
  tim.tm_sec  = 0;
/* take daylight saving time flag and gmt offset from today */
  my_base=mktime(&tim) - 12*3600;
  assert(tim.tm_wday == 1); /* time base must be a monday */
}

int mycNow(void) {
  time_t now;

  if (my_base == 0) initBase();
  time(&now);
  return (int)(now-my_base);
}

time_t mycUnixTime(int myTime) {
  return myTime+my_base;
}

int mycMsecSince(int since) {
#if __VMS
  struct timeb now;
#else
  struct timeval now;
#endif
  int msec;

  if (my_base == 0) initBase();
#if __VMS
  ftime(&now);
  msec = (now.time - my_base) % (24*3600) * 1000 + now.millitm - since;
#else
  gettimeofday(&now, NULL);
  msec = (now.tv_sec - my_base) % (24*3600) * 1000 + now.tv_usec/1000 - since;
#endif
  if (msec < 0) msec+=24*3600000;
  return msec;
}

int mycDate(int time) {
  struct tm tim;
  time_t t;

  if (my_base == 0) initBase();
  t = time + my_base;
  tim=*localtime(&t);
  return (tim.tm_year + 1900) * 10000 + (tim.tm_mon + 1) * 100 + tim.tm_mday;
}

int mycTime(int date) {
  struct tm tim;
  time_t now;
  int y, m, d;

  if (my_base == 0) initBase();
  time(&now);
  tim=*localtime(&now);
  tim.tm_hour=0;
  tim.tm_min=0;
  tim.tm_sec=0;
  if (date != 0) {
    d = date % 100;
    date = date / 100;
    m = date % 100;
    y = date / 100;
    if (y == 0) {
      if (m == 0) {
        if (d > tim.tm_mday) {
          if (tim.tm_mon == 0) { /* jan */
            tim.tm_mon=11; /* dec */
            tim.tm_year--;
          } else {
            tim.tm_mon--; /* last month */
          }
        }
      } else {
        tim.tm_mon = m - 1;
      }
    } else {
      tim.tm_year = y - 1900;
      if (m == 0) {
        if (d == 0) {
          tim.tm_mon = 0;
        }
      } else {
        tim.tm_mon = m - 1;
      }
    }
    if (d == 0) d = 1;
    tim.tm_mday = d;
  }
  return (int)(mktime(&tim)-my_base);
}


/* fortran routines --------------------------------------------------
*/

#ifdef F_CHAR
/* compile only when fortran c interface stuff is defined */

int F_FUN(myc_now)(void) { return mycNow(); }
int F_FUN(myc_date)(int *time) { return mycDate(*time); }
int F_FUN(myc_time)(int *date) { return mycTime(*date); }

#endif
