/* Show info in a tz file */

#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <time.h>
#include "tzfile.h"

/* convert the bytes of a 32-bit integer to little endian */
#define BSWAP32(c) ((c>>24)&0xff)|((c>>8)&0xff00)|((c<<8)&0xff0000)|(c<<24)

struct tzhead h;
struct ttinfo ti;

int tzh_ttisgmtcnt, tzh_ttisstdcnt, tzh_leapcnt, tzh_timecnt,
   tzh_typecnt, tzh_charcnt;


int read_hdr(int f)
{
   if ((read(f, &h, sizeof(h))) == -1) {
       perror("read");
       return 0;
   }
   tzh_ttisgmtcnt = BSWAP32(*((int *)h.tzh_ttisgmtcnt));
   tzh_ttisstdcnt = BSWAP32(*((int *)h.tzh_ttisstdcnt));
   tzh_leapcnt = BSWAP32(*((int *)h.tzh_leapcnt));
   tzh_timecnt = BSWAP32(*((int *)h.tzh_timecnt));
   tzh_typecnt = BSWAP32(*((int *)h.tzh_typecnt));
   tzh_charcnt = BSWAP32(*((int *)h.tzh_charcnt));

   printf("Header Values\n\n");
   printf("tzh_ttisgmtcnt: %d\n", tzh_ttisgmtcnt);
   printf("tzh_ttisstdcnt: %d\n", tzh_ttisstdcnt);
   printf("tzh_leapcnt: %d\n", tzh_leapcnt);
   printf("tzh_timecnt: %d\n", tzh_timecnt);
   printf("tzh_typecnt: %d\n", tzh_typecnt);
   printf("tzh_charcnt: %d\n", tzh_charcnt);
}

int main(int argc, char **argv)
{
   int f, i;
   char *type_ndx;
   time_t *trans_time;
   struct ttinfo *ti;
   char *abbr;
   char *is_std;
   char *is_gmt;
   int tmp;
   char s[256];
   struct tm *tm;
   char *set_isdst_s[2] = {"No", "Yes"};
   char *std_s[2] = {"Wall", "Std"};
   char *gmt_s[2] = {"Local", "GMT"};

   if (argc == 1) {
       fprintf(stderr, "usage: tzshow <tzfile>\n");
       exit(0);
   }

   if ((f = open(argv[1], O_RDONLY)) == -1) {
       perror("open");
       exit(1);
   }

   if (! read_hdr(f))
       exit(1);

   trans_time = (time_t *)malloc(tzh_timecnt * sizeof(time_t));
   for (i = 0; i < tzh_timecnt; i++) {
       read(f, &tmp, 4);
       trans_time[i] = BSWAP32(tmp);
   }

   type_ndx = (char *)malloc(tzh_timecnt * sizeof(char));
   for (i = 0; i < tzh_timecnt; i++)
       read(f, &(type_ndx[i]), 1);

   ti = (struct ttinfo *)malloc(tzh_typecnt * sizeof(struct ttinfo));
   for (i = 0; i < tzh_typecnt; i++)
       read(f, &(ti[i]), sizeof(struct ttinfo));

   abbr = (char *)malloc(tzh_charcnt);
   read(f, abbr, tzh_charcnt);

   for (i = 0; i < tzh_leapcnt; i++) {
       read(f, &tmp, sizeof(tmp));
       read(f, &tmp, sizeof(tmp));
   }

   is_std = (char *)malloc(tzh_ttisstdcnt * sizeof(char));
   for (i = 0; i < tzh_ttisstdcnt; i++)
       read(f, &(is_std[i]), sizeof(char));

   is_gmt = (char *)malloc(tzh_ttisgmtcnt * sizeof(char));
   for (i = 0; i < tzh_ttisgmtcnt; i++)
       read(f, &(is_gmt[i]), sizeof(char));

   printf("\n\nTransitions\n\n");
   printf("%-30s%s\n\n",  "Date", "Local Time Type");

   for (i = 0; i < tzh_timecnt; i++) {
       tm = gmtime(&(trans_time[i]));
//      strftime(s, 255, "%Y-%m-%d %H:%M", tm);
       strcpy(s, asctime(tm));
       s[strlen(s) - 1] = '\0';
       printf("%-30s%d\n", s, type_ndx[i]);
   }

   printf("\n\nLocal Time Types\n\n");
   printf("%-5s%-10s%-15s%-8s%-12s%s\n\n", "Nr", "GMT Off",
           "Set tm_isdst", "Abbr", "Std/Wall", "GMT/Local");

   for (i = 0; i < tzh_typecnt; i++) {
       printf("%-5d%-10d%-15s%-8s%-12s%s\n",
               i, (BSWAP32(*((int *)(ti[i].tt_gmtoff)))) / 3600,
               set_isdst_s[ti[i].tt_isdst], abbr + ti[i].tt_abbrind,
               std_s[is_std[i]], gmt_s[is_gmt[i]]);
   }

   close(f);
   return 0;
}