/*
 *  graphfree.c
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "oslib/osfile.h"
#include "oslib/osfscontrol.h"
#include "oslib/osword.h"
#include "oslib/territory.h"
#include "oslib/wimp.h"


char **message_table;

void die(const char *message);
char **messages_read(const char *file_name);
unsigned long long used_space(const char *disc);
unsigned long long current_time(void);
void format_time(char *buffer, int size, const char *format);
void print_ulonglong(FILE *stream, unsigned long long x);
int main(void);


void die(const char *message)
{
  os_error error;

  error.errnum = 1;
  strcpy(error.errmess, message);
  xwimp_command_window(-1);
  xwimp_report_error_by_category(&error, wimp_ERROR_BOX_CANCEL_ICON |
      wimp_ERROR_BOX_GIVEN_CATEGORY | wimp_ERROR_BOX_CATEGORY_ERROR,
      "GraphFree", "!graphfree", (osspriteop_area *) 1, NULL, NULL);
  exit(EXIT_FAILURE);
}


char **messages_read(const char *file_name)
{
  char *data;
  char **table;
  unsigned int size = 0, count = 0, pos = 0, i, len;
  int c;
  FILE *file;

  file = fopen(file_name, "rb");
  if (file == NULL) die("unable to open messages file");

  while ((c = fgetc(file)) != EOF)
  {
    size++;
    if (c == '\n') count++;
  }
  size++;

  data = malloc(size);
  if (data == NULL) die("out of memory");
  table = calloc(count, sizeof(char *));
  if (table == NULL) die("out of memory");

  if (fseek(file, 0, SEEK_SET)) die("file seek failed");

  for (i = 0; i < count; i++)
  {
    if (!fgets(data + pos, size - pos, file)) die("fgets failed");
    len = strlen(data + pos);
    data[pos + len - 1] = '\0';
    table[i] = data + pos;
    pos += len;
  }

  fclose(file);

  return table;
}


unsigned long long used_space(const char *disc)
{
  unsigned int free_lo, free_hi, size_lo, size_hi;
  unsigned long long free, size;
  os_error *error;

  error = xosfscontrol_free_space64(disc, &free_lo, &free_hi, NULL, &size_lo, &size_hi);
  if (error != NULL)
  {
    error = xosfscontrol_free_space(disc, &free_lo, NULL, &size_lo);
    if (error != NULL)
    {
      char message[500];
      sprintf(message, message_table[0], disc, error->errmess);
      die(message);
    }
    free_hi = size_hi = 0;
  }

  free = ((unsigned long long) free_hi) << 32 | free_lo;
  size = ((unsigned long long) size_hi) << 32 | size_lo;

  return size - free;
}


unsigned long long current_time(void)
{
  oswordreadclock_utc_block utc;
  os_error *error;

  utc.op = oswordreadclock_OP_UTC;
  error = xoswordreadclock_utc(&utc);
  if (error != NULL) die(error->errmess);

  return (unsigned long long) utc.utc[0] |
         (unsigned long long) utc.utc[1] << 8 |
         (unsigned long long) utc.utc[2] << 16 |
         (unsigned long long) utc.utc[3] << 24 |
         (unsigned long long) utc.utc[4] << 32;
}


void format_time(char *buffer, int size, const char *format)
{
  oswordreadclock_utc_block utc;
  os_error *error;

  utc.op = oswordreadclock_OP_UTC;
  error = xoswordreadclock_utc(&utc);
  if (error != NULL) die(error->errmess);

  error = xterritory_convert_date_and_time(territory_CURRENT,
      &utc.utc, buffer, size, format, NULL);
  if (error != NULL) die(error->errmess);
}


void print_ulonglong(FILE *stream, unsigned long long x)
{
  char s[32];
  int i = 31;

  s[i] = '\0';
  while (x)
  {
    s[--i] = "0123456789"[x % 10];
    x /= 10;
  }
  fprintf(stream, s + i);
}


int main(void)
{
  FILE *discs;
  char line[200];

  message_table = messages_read("<GraphFree$Messages>");

  discs = fopen("<Obey$Dir>.Discs.Discs", "r");
  if (discs == NULL) die(message_table[1]);

  while (fgets(line, 200, discs))
  {
    line[strlen(line) - 1] = '\0';
    if ((line[0] != '#') && (line[0] != '\0'))
    {
      char buffer[200];
      unsigned long long used, time;
      FILE *out;
      os_error *error;

      used = used_space(line);
      time = current_time();

      sprintf(buffer, "<Obey$Dir>.Discs.%s", strchr(line, ':') + 2);
      out = fopen(buffer, "a");
      if (out == NULL) die(message_table[3]);

      if (ftell(out) == 0) fprintf(out, "%s\n", message_table[5]);

      format_time(buffer, 200, message_table[4]);
      fprintf(out, "\"%s\",", buffer);
      print_ulonglong(out, time);
      fprintf(out, ",");
      print_ulonglong(out, used);
      fprintf(out, "\n");

      fclose(out);

      sprintf(buffer, "<Obey$Dir>.Discs.%s", strchr(line, ':') + 2);
      error = xosfile_set_type(buffer, 0xdfe);
      if (error != NULL) die(error->errmess);
    }
  }

  return 0;
}
