#include "qjs_time.h"
#include <time.h>
#include <sys/time.h>

/* ---------------------------------------------------------------- *\
   Helpers
\* ---------------------------------------------------------------- */

/* Seconds from Misty epoch (year-0) so JS “number()” stays consistent.
   62167219200 = seconds between 0000-01-01 00:00 UTC and 1970-01-01 00:00 UTC. */
static inline double misty_now(void)
{
  struct timeval tv;
  gettimeofday(&tv, NULL);
  return (double)tv.tv_sec + tv.tv_usec / 1000000.0;
}

/* ---------------------------------------------------------------- *\
   JS bindings
\* ---------------------------------------------------------------- */

static JSValue
js_time_now(JSContext *ctx, JSValueConst this_val,
            int argc, JSValueConst *argv)
{
  return JS_NewFloat64(ctx, misty_now());
}

static JSValue
js_time_computer_dst(JSContext *ctx, JSValueConst this_val,
                     int argc, JSValueConst *argv)
{
  time_t t = time(NULL);
  struct tm *lt = localtime(&t);
  return JS_NewBool(ctx, lt && lt->tm_isdst > 0);
}

static JSValue
js_time_computer_zone(JSContext *ctx, JSValueConst this_val,
                      int argc, JSValueConst *argv)
{
  time_t t = time(NULL);

#ifdef __USE_BSD                       /* tm_gmtoff / tm_zone available */
  struct tm lt = *localtime(&t);
  long offset_sec = lt.tm_gmtoff;      /* seconds east of UTC           */
#else                                   /* portable fallback            */
  struct tm gmt = *gmtime(&t);

  /* Trick: encode the *same* calendar fields as “local” and see
     how many seconds they represent.                         */
  gmt.tm_isdst = 0;                    /* mktime expects valid flag     */
  time_t local_view = mktime(&gmt);    /* same Y-M-D H:M:S but local    */

  long offset_sec = t - local_view;    /* negative west of UTC          */
#endif

  return JS_NewFloat64(ctx, (double)offset_sec / 3600.0);
}

/* ---------------------------------------------------------------- *\
   registration
\* ---------------------------------------------------------------- */

static const JSCFunctionListEntry js_time_funcs[] = {
  JS_CFUNC_DEF("now",           0, js_time_now),
  JS_CFUNC_DEF("computer_dst",  0, js_time_computer_dst),
  JS_CFUNC_DEF("computer_zone", 0, js_time_computer_zone),
};

JSValue
js_time_use(JSContext *ctx)
{
  JSValue obj = JS_NewObject(ctx);
  JS_SetPropertyFunctionList(ctx, obj,
                             js_time_funcs,
                             sizeof(js_time_funcs) /
                             sizeof(js_time_funcs[0]));
  return obj;
}
