#include <err.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#define NAME_SIZE 64

struct State {
	int counter;
	time_t updated_at;
	char name[NAME_SIZE];
	size_t history_entries;
};

static char *names[] = {
	"boingo",
	"barko",
	"flip",
	"dingles",
	"zebra",
	"horus",
	"blendy",
	"kitems",
	"horple",
	NULL,
};

char *random_name()
{
	int i = 0;
	int mod = 0;
	for (i = 0; names[i] != NULL; i++) {
		mod = i;
	}

	return names[random() % mod];
}

void tick(FILE *fp, int init)
{
	struct State *state = malloc(sizeof(struct State));
	if (!state) {
		err(EXIT_FAILURE, "Memory error making State");
	}

	if (init == 0) {
		size_t read = fread(state, sizeof(struct State), 1, fp);

		fprintf(
			stderr,
			"Read %d \"%s\" (%lu byte(s)) from %lu\n",
			state->counter, state->name, sizeof(struct State) * read, state->updated_at
		);
	}

	time_t history[state->history_entries];
	size_t histories_read = fread(&history, sizeof(time_t), state->history_entries, fp);

	state->counter++;
	state->updated_at = time(0);
	strncpy(state->name, random_name(), NAME_SIZE);
	state->history_entries++;

	rewind(fp);

	size_t wrote = fwrite(state, sizeof(struct State), 1, fp);
	fwrite(history, sizeof(time_t), sizeof(history) / sizeof(time_t), fp);
	fwrite(&state->updated_at, sizeof(time_t), 1, fp);

	fprintf(
		stderr,
		"Wrote %d \"%s\" (%lu byte(s)) at %lu (history length=%lu)\n",
		state->counter, state->name, sizeof(struct State) * wrote, state->updated_at,
		state->history_entries
	);
}

int main(int argc, char *argv[])
{
	if (argc < 2) {
		errx(EXIT_FAILURE, "Missing filename argument");
	}

	int random_seed = time(0);
	const char *random_seed_str = getenv("RANDOM_SEED");
	if (random_seed_str) {
		random_seed = atoi(random_seed_str);
	}

	srandom(random_seed);

	int init = 0;
	FILE *fp = fopen(argv[1], "r+");

	if (!fp) {
		fp = fopen(argv[1], "w+");
		init = 1;
	}

	if (!fp) {
		err(EXIT_FAILURE, "Failed to open file");
	}

	tick(fp, init);
	fclose(fp);

	return 0;
}
