// : out wip


/*
I have the following spec, I need you to write a C program that fills this spec:

- this program is called 'wip' and will record 'updates'
- an 'update' is a line of text with a timestamp
- this program should use 'argp.h' for processing command line arguments
- The command line interface has two subcommands, "submit" and "review"
- submit command:
  - takes a line of text and writes the timestamp and line of text separated by a tab to a file called 'wip.dat'. This represents one 'update'
  - the timestamp format should be "%Y-%m-%d %H:%M:%S"
- review command:
  - reads the file 'wip.dat' and prints all the updates for the given week.
  - takes an flag '--period' for determining which week to report updates for
  - '--period' takes an argument which can be either 'thisweek' or 'lastweek', defaulting to 'thisweek' if not given


Here is some example usage:

$ wip submit "This is my update"
$ wip submit "This is a second update"
$ wip review
Updates for this week:
  + This is my update
  + This is a second update
$ wip review -p thisweek
Updates for this week:
  + This is my update
  + This is a second update
$ wip review --period lastweek
  + this was an update from last week
*/


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

#define WIP_FILENAME "wip.dat"
#define TIMESTAMP_FORMAT "%Y-%m-%d %H:%M:%S"

const char *argp_program_version = "wip 1.0";
const char *argp_program_bug_address = "<your-email@example.com>";

static char doc[] = "A simple tool to record and review updates";

static struct argp_option options[] = {
  {"period", 'p', "PERIOD", 0,
   "Set the period for review (thisweek, lastweek)"},
  {0}
};

struct arguments
{
  char *command;
  char *update;
  char *period;
};

static error_t
parse_opt (int key, char *arg, struct argp_state *state)
{
  struct arguments *arguments = state->input;
  switch (key)
    {
    case 'p':
      arguments->period = arg;
      break;
    case ARGP_KEY_ARG:
      if (arguments->command == NULL)
	{
	  arguments->command = arg;
	}
      else if (arguments->update == NULL)
	{
	  arguments->update = arg;
	}
      break;
    default:
      return ARGP_ERR_UNKNOWN;
    }
  return 0;
}

static struct argp argp = { options, parse_opt, "COMMAND [UPDATE]", doc };

void
submit_update (char *update)
{
  FILE *file = fopen (WIP_FILENAME, "a");
  if (file == NULL)
    {
      printf ("Could not open %s\n", WIP_FILENAME);
      return;
    }

  time_t now;
  time (&now);
  struct tm *timeinfo = localtime (&now);

  char timestamp[20];
  strftime (timestamp, sizeof (timestamp), TIMESTAMP_FORMAT, timeinfo);

  fprintf (file, "%s\t%s\n", timestamp, update);

  fclose (file);
}

void
review_updates (char *period)
{
  FILE *file = fopen (WIP_FILENAME, "r");
  if (file == NULL)
    {
      printf ("Could not open %s\n", WIP_FILENAME);
      return;
    }

  time_t now;
  time (&now);
  struct tm *timeinfo = localtime (&now);
  int current_week = timeinfo->tm_yday / 7;
  if (strcmp (period, "lastweek") == 0)
    {
      current_week--;
    }

  char line[256];
  while (fgets (line, sizeof (line), file))
    {
      struct tm timeinfo_line = { 0 };
      strptime (line, TIMESTAMP_FORMAT, &timeinfo_line);
      int line_week = timeinfo_line.tm_yday / 7;

      if (line_week == current_week)
	{
	  printf ("+ %s", strchr (line, '\t') + 1);
	}
    }

  fclose (file);
}

int
main (int argc, char **argv)
{
  struct arguments arguments;
  arguments.command = NULL;
  arguments.update = NULL;
  arguments.period = "thisweek";

  argp_parse (&argp, argc, argv, 0, 0, &arguments);

  if (arguments.command == NULL)
    {
      printf ("No command provided. Expected 'submit' or 'review'.\n");
      return 1;
    }

  if (strcmp (arguments.command, "submit") == 0)
    {
      if (arguments.update == NULL)
	{
	  printf ("No update provided for 'submit' command.\n");
	  return 1;
	}
      submit_update (arguments.update);
    }
  else if (strcmp (arguments.command, "review") == 0)
    {
      review_updates (arguments.period);
    }
  else
    {
      printf ("Unknown command '%s'. Expected 'submit' or 'review'.\n",
	      arguments.command);
      return 1;
    }

  return 0;
}