/*
 * $Id$
 *
 * :ts=4
 *
 * AmigaOS wrapper routines for GNU CVS, using the AmiTCP V3 API
 * and the SAS/C V6.58 compiler.
 *
 * Written and adapted by Olaf `Olsen' Barthel <olsen@sourcery.han.de>
 *                        Jens Langner <Jens.Langner@htw-dresden.de>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <exec/memory.h>

#include <dos/dosextens.h>
#include <dos/dostags.h>

#include <clib/exec_protos.h>
#include <clib/dos_protos.h>
#include <clib/utility_protos.h>

#include <pragmas/exec_sysbase_pragmas.h>
#include <pragmas/dos_pragmas.h>
#include <pragmas/utility_pragmas.h>

#include <stdio.h>
#include <dos.h>
#include <time.h>

/****************************************************************************/

/*#define DEBUG*/
#include "_assert.h"

/****************************************************************************/

#define UNIX_TIME_OFFSET 252460800

/****************************************************************************/

extern struct Library * DOSBase;
extern struct Library * UtilityBase;

/****************************************************************************/

extern int amiga_get_minutes_west(void);

/******************************************************************************/

void
__tzset(void)
{
   static char time_zone_name[20] = "";

   /* This routine sets up the internal
    * time zone variable according to
    * the local settings.
    */
   if(time_zone_name[0] == '\0')
   {
      int hours_west = amiga_get_minutes_west() / 60;

      if(hours_west >= 0)
         sprintf(time_zone_name,"GMT+%02d", hours_west);
      else
         sprintf(time_zone_name,"GMT-%02d",-hours_west);
   }

   _TZ = time_zone_name;
}

/******************************************************************************/

time_t
time(time_t *timeptr)
{
   time_t currentTime;
   struct DateStamp ds;
   LONG seconds;

   chkabort();

   DateStamp(&ds);

   seconds  = ((ds.ds_Days * 24 * 60) + ds.ds_Minute) * 60 + (ds.ds_Tick / TICKS_PER_SECOND);

   currentTime = UNIX_TIME_OFFSET + seconds + 60 * amiga_get_minutes_west();  /* translate from local time to UTC */

   if(timeptr != NULL)
      (*timeptr) = currentTime;

   return(currentTime);
}

/******************************************************************************/

STATIC struct tm *
ConvertTime(ULONG seconds)
{
   STATIC struct tm tm;

   struct ClockData clockData;
   ULONG delta;

   chkabort();

   Amiga2Date(seconds,&clockData);

   tm.tm_sec   = clockData.sec;
   tm.tm_min   = clockData.min;
   tm.tm_hour  = clockData.hour;
   tm.tm_mday  = clockData.mday;
   tm.tm_mon   = clockData.month - 1;
   tm.tm_year  = clockData.year - 1900;
   tm.tm_wday  = clockData.wday;
   tm.tm_isdst = 0;

   clockData.mday = 1;
   clockData.month   = 1;

   delta = Date2Amiga(&clockData);

   tm.tm_yday = (seconds - delta) / (24*60*60);

   return(&tm);
}

char *
asctime(const struct tm * tm)
{
   static char * month_names[12] =
   {
      "Jan","Feb","Mar","Apr",
      "May","Jun","Jul","Aug",
      "Sep","Oct","Nov","Dec"
   };

   static char * day_names[7] =
   {
      "Sun","Mon","Tue","Wed",
      "Thu","Fri","Sat"
   };

   static char result_buffer[40];
   char * month_name;
   char * day_name;

   month_name = (0 <= tm->tm_mon && tm->tm_mon < 12) ? month_names[tm->tm_mon] : "---";
   day_name = (0 <= tm->tm_wday && tm->tm_wday < 7) ? day_names[tm->tm_wday] : "---";

   sprintf(result_buffer,"%s %s %02d %02d:%02d:%02d %d\n",
      day_name,
      month_name,
      tm->tm_mday,
      tm->tm_hour,tm->tm_min,tm->tm_sec,
      tm->tm_year + 1900);

   return(result_buffer);
}

char *
ctime(const time_t * t)
{
   char * result;

   result = asctime(localtime(t));

   return(result);
}

struct tm *
gmtime(const time_t *t)
{
   struct tm * result;
   ULONG seconds;

   if((*t) < UNIX_TIME_OFFSET)
      seconds = 0;
   else
      seconds = (*t) - UNIX_TIME_OFFSET;

   result = ConvertTime(seconds);

   return(result);
}

struct tm *
localtime(const time_t *t)
{
   struct tm * result;
   ULONG seconds;

   if((*t) < (UNIX_TIME_OFFSET + 60 * amiga_get_minutes_west()))
      seconds = 0;
   else
      seconds = (*t) - (UNIX_TIME_OFFSET + 60 * amiga_get_minutes_west()); /* translate from UTC to local time */

   result = ConvertTime(seconds);

   return(result);
}
