#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <time.h>
#include "raw2sac.h"


void byteswap32(uint32_t *p, unsigned int length)
{
  int i;
  for (i = 0; i < length; i++) {
    p[i] = ((p[i] & 0x000000ff) << 24) |
          ((p[i] & 0x0000ff00) << 8)  |
          ((p[i] & 0x00ff0000) >> 8)  |
          ((p[i] & 0xff000000) >> 24);
  }
}

int main(int argc, char * argv[])
{
  FILE *input;
  FILE *output;
  time_t current;
  time_t start = 0;
  time_t end = time(0);
  struct tm *current_tm;
  sac_header header = sac_default;
  int16_t scratch;
  unsigned int length;
  float *vals;
  uint16_t v1, v2;

  if (argc != 3 && argc != 4 && argc != 5) {
    printf("Usage: %s <input file> <output file> [<Unix start time>] [<Unix end time>]\n", argv[0]);
    return -1;
  }

  input = fopen(argv[1], "rb");
  if (!input) {
    printf("%s: Could not open input file %s.\n", argv[0], argv[1]);
    return -1;
  }

  fseek(input, 0, SEEK_END);
  length = ftell(input);
  rewind(input);
  vals = malloc(length / 2 * sizeof(float));

  if (!vals) {
    printf("%s: Couldn't allocate %d bytes.\n",
	   argv[0], length / 2 * sizeof(float));
    return -1;
  }


  output = fopen(argv[2], "wb");
  if (!output) {
    printf("%s: Could not open output file %s.\n", argv[0], argv[2]);
    return -1;
  }

  if (argc > 3)
    start = atoi(argv[3]);

  if (argc > 4)
    end = atoi(argv[4]);

  do {
    v2 = fgetc(input);
    do {
      v1 = v2;
      v2 = fgetc(input);
    } while (v1 != 0x80 || v2 != 0x00 && !feof(input));
    
    if (feof(input)) {
      printf("Unexpected end of file\n");
      return -1;
    }
    current =
      ((uint8_t)fgetc(input) << 24) |
      ((uint8_t)fgetc(input) << 16) |
      ((uint8_t)fgetc(input) << 8) |
      ((uint8_t)fgetc(input) << 0);
  } while (current < start || current > time(0));

  if (current < 1313482080)
    current -= 5;

  current_tm = gmtime(&current);

  printf("Starting at %4d-%02d-%02d %02d:%02d:%02d (julian %d)\n",
	 current_tm->tm_year + 1900,
	 current_tm->tm_mon + 1,
	 current_tm->tm_mday,
	 current_tm->tm_hour,
	 current_tm->tm_min,
	 current_tm->tm_sec,
	 current_tm->tm_yday + 1);

  length = 0;
  while (fread((void *)&scratch, sizeof(scratch), 1, input) == 1)
  {
    scratch = scratch << 8 | (scratch >> 8) & 0xff;
    if (scratch == -32768) {
      int32_t scratch2;
      current =
	((uint8_t)fgetc(input) << 24) |
	((uint8_t)fgetc(input) << 16) |
	((uint8_t)fgetc(input) << 8) |
	((uint8_t)fgetc(input) << 0);
      if (current > end || feof(input))
        break;
      continue;
    }
    vals[length++] = (float)scratch;
  }
  fclose(input);

  header.sens = 1.0;

  header.lNpt = length;
  header.internal4 = 6;
  header.start_sec = 0.0;
  header.end_sec = 0.0;
  header.iftype = ITIME;
  header.leven = 1;

  header.year = current_tm->tm_year + 1900;
  header.jj = current_tm->tm_yday + 1;
  header.hh = current_tm->tm_hour;
  header.mm = current_tm->tm_min;
  header.ss = current_tm->tm_sec;
  header.milli = 0;

  header.lat = 59.97;
  header.lon = 10.65;
  header.el = 339;
  header.stdp = 4;
  header.cmpaz = 0;
  header.cmpinc = 90;
  header.ax[0] = header.ax[1] = header.ax[2] = header.ax[4] =
    header.ax[5] = header.ax[6] = header.ax[7] = 0;
  header.staname[3] = 'o';
  header.staname[2] = 's';
  header.staname[1] = 'l';
  header.staname[0] = 'o';
  header.staname[7] = 0;
  header.staname[6] = 0;
  header.staname[5] = 0;
  header.staname[4] = 0;

  if (!strncmp(argv[1] + strlen(argv[1]) - 9, "geo_n.raw", 5)) {
    header.ax[3] = 'N';
    header.dt = 0.01;
  } else if (!strncmp(argv[1] + strlen(argv[1]) - 9, "geo_e.raw", 5)) {
    header.ax[3] = 'E';
    header.dt = 0.01;
  } else if (!strncmp(argv[1] + strlen(argv[1]) - 9, "geo_z.raw", 5)) {
    header.ax[3] = 'Z';
    header.dt = 0.01;
  } else {
    header.ax[3] = 'N';
    header.dt = 0.05;
  }

  printf("Writing %d samples %f (%.0f minutes)\n", length, header.dt, length * header.dt / 60);

  current_tm = gmtime(&current);

  printf("Ending at %4d-%02d-%02d %02d:%02d:%02d (julian %d)\n",
	 current_tm->tm_year + 1900,
	 current_tm->tm_mon + 1,
	 current_tm->tm_mday,
	 current_tm->tm_hour,
	 current_tm->tm_min,
	 current_tm->tm_sec,
	 current_tm->tm_yday + 1);

  byteswap32((uint32_t*)&header, sizeof(header) / 4);
  byteswap32((uint32_t*)vals, length);
  fwrite(&header, sizeof(header), 1, output);
  fwrite(vals, sizeof(float), length, output);

  fclose(output);

  return 0;
}
