#include <sys/types.h>
#include <sys/time.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <assert.h>
#include <zlib.h>

/* including main header file */
#include "mud.h"


CHANGE_DATA *change_list = NULL;
CHANGE_DATA *change_last = NULL;
CHANGE_DATA *change_free = NULL;

void add_changefile(char *name, char *date, char *text);
FILE *fpReserve; 

bool remove_change   (int i);

void load_changes()
{
    CHANGE_DATA *change;
    FILE *fp;
    char *name;

    if ((fp = fopen(CHANGE_FILE, "r")) == NULL)
    {
        log_string("Non-fatal error: changes.txt not found!");
        return;
    }
    name = fread_word(fp);
    while (compares(name, END_MARKER))
    {
        change = malloc(sizeof(CHANGE_DATA));
        change->imm  = strdup(name);
        change->date = fread_string(fp);
        change->text = fread_string(fp);

        if (change_list)
            change_list->prev = change;
        change->next = change_list;
        change_list = change;

        if (!change_last)
            change_last = change;
        name = fread_word(fp);
    }

    fclose(fp);
}

void save_changes()
{
    FILE *fp;
    CHANGE_DATA *change;
    int i = 0;

    if ((fp = fopen("../txt/changes.txt","w")) == NULL)
    {
        log_string("Error writing to changes.txt");
        return;
    }
    for (change = change_last; change; change = change->prev)
    {
        if (++i > MAX_CHANGE)
            break;
        fprintf(fp, "%s\n", change->imm);
        fprintf(fp, "%s~\n", change->date);
        fprintf(fp, "%s~\n", change->text);
    }
    fprintf(fp, "%s\n", END_MARKER);
    fclose(fp);
}

void do_addchange( D_MOBILE *ch, char *argument )
{
    CHANGE_DATA *change;
    CHANGE_DATA *cchange;
    char *strtime;
    char buf[MAX_BUFFER];
    int i;

  /* we need something to add to the list */
  if (argument[0] == '\0' || strlen(argument) < 5)
  {
    stc("What did you change?\n\r", ch);
    return;
  }
  /* Mainly to avoid that the list looks ugly */
  if (strlen(argument) > 120)
  {
    stc("Keep it on 120 chars please.\n\r", ch);
    return;
  }

  /* Set the current time */
  strtime = ctime(&current_time);
  for (i = 0; i < 6; i++)
  {
    buf[i] = strtime[i + 4];
  }
  buf[6] = '\0';

  /* If we have a free change, we reuse it */
  if (change_free)
  {
    change = change_free;
    change_free = change_free->next;
    change->next = NULL;
    if (change_free) change_free->prev = NULL;
  }
  else
    change = malloc(sizeof(*change));

  /* set the strings for the change */
  change->imm = strdup(ch->name);
  change->text = strdup(argument);
  change->date = strdup(buf);

    add_changefile(strdup(ch->name), strdup(buf), strdup(argument));
    

  /* If theres already a change, just add to the list */
  if (change_last)
  {
    change_last->next = change;
    change->prev = change_last;
    change->next = NULL;
    change_last = change;
  }
  else /* there are no changes. */
  {
    change->next = change_list;
    change_list = change;
    change_last = change;
  }

  /* Removing the oldest change if the list has gone beyond the max */
  cchange = change_list; i = 0;
  while ((cchange = cchange->next) != NULL) i++;
  if (i >= MAX_CHANGE)
    remove_change(1);

  stc("Change added.\n\r", ch );  
  save_changes();
  return;
}

void add_changefile(char *name, char *date, char *text)
{
    FILE *fp;
    char buf[MAX_BUFFER];
    buf[0] = '\0';
    
    if ( (fp = fopen(CHANGE2_FILE, "a") ) == NULL)
    {
        log_string("Unable to open changelog.txt!\n");
    }
    else
    {
        sprintf(buf, "%-7s %-7s %s\n", name, date, text);
        fprintf(fp, buf);
        fclose( fp );
    }
    return;
}

void cmd_clearchanges (D_MOBILE * ch, char *arg)
{
    FILE *fp;
    char *strtime;
    char buf[MAX_BUFFER];
    int i;
    int result;
    char oldname[] = CHANGE2_FILE;
    char newname[MAX_BUFFER];
    
    
    strtime = ctime(&current_time);
    for (i = 0; i < 6; i++)
    {
        buf[i] = strtime[i + 4];
    }
    buf[6] = '\0';
    
        
    /* Lets backup the file first */
    sprintf(newname, "%schanges.txt", buf);
    /* Get rid of Spaces! */
    smash_space(newname);
    result = rename(oldname, newname);
    if (result != 0 )
    {
        log_string("clearchanges(): Failed renaming");
        return;
    }

    if ( (fp = fopen(CHANGE2_FILE, "w") ) == NULL)
    {
        log_string("Unable to open changelog.txt!\n");
    }
    else
    {
        fprintf(fp, "\n\n- = - = - = - Changes since %s\n\n", buf);
        fprintf(fp, "- = - = - = - See %s to see Older changes\n\n", newname);
        fclose( fp );
    }
    return;
}
void do_changes(D_MOBILE *ch, char *argument)
{
  CHANGE_DATA *change;
  char buf[MAX_BUFFER];
  char tempbuf[MAX_BUFFER];
  bool found = FALSE;
  int i = 0;

  sprintf(buf, " [***] Code Changes Since Reboot && Random Messages [***]\n\r\n\r");
  for (change = change_list; change; change = change->next)
  {
    found = TRUE;
    ++i;
    sprintf(tempbuf, " [%3d] %-6s  %-9s %s\n\r",
      i, change->date, change->imm, change->text);
    strcat(buf, tempbuf);
  }
  if (found)
      stc(buf, ch);
  else stc("No changes.\n\r", ch);
  return;
}

void do_delchange(D_MOBILE *ch, char *argument)
{
  char arg[MAX_OUTPUT];
  bool found = FALSE;
  int i;

  one_arg(argument, arg);

  if ((i = atoi(arg)) < 1)
  {
    stc("Which number change did you want to remove ?\n\r", ch);
    return;
  }
  found = remove_change(i);
  if (!found) stc("No such change.\n\r", ch);
  else stc("Change removed.\n\r", ch);
  save_changes();
  return;
}

/*
 * This function handles the actual removing of the change
 */
bool remove_change(int i)
{
  CHANGE_DATA *change;
  bool found = FALSE;

  for (change = change_list; change; change = change->next)
  {
    if (--i > 0) continue;
    found = TRUE;

    /* update the pointer to the last change if needed */
    if (change == change_last) change_last = change->prev;

    /* handle the special case of the first change */
    if (change == change_list)
    {
      change_list = change->next;
      if (change->next) change->next->prev = NULL;
    }
    else
    {
      change->prev->next = change->next;
      if (change->next)
        change->next->prev = change->prev;
    }

    /* Handle the free list */
    change->next = change_free;
    change->prev = NULL;
    if (change_free) change_free->prev = change;
    change_free = change;

    /* terminate the loop */
    break;
  }

  /* did we remove anything ? */
  return found;
}