/* Property of Owen Emlen and Simon Lee - some borrowed from older code, 90% new */
#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "emlen.h"
bool is_note_to (CHAR_DATA * ch, NOTE_DATA * pnote);
void note_attach (CHAR_DATA * ch);
void note_remove (CHAR_DATA * ch, NOTE_DATA * pnote);
void note_delete (NOTE_DATA * pnote);

#define MAX_BOARDS 4
char *boards[MAX_BOARDS] = {
"Blank",
"Immortal Notice Board",
"General Chat Board",
"Ideas/Complaint Board"
};

bool 
is_note_to (CHAR_DATA * ch, NOTE_DATA * pnote)
{
  if (!str_cmp (NAME (ch), pnote->sender))
    return TRUE;
  if (is_name ("all", pnote->to_list) || is_name ("clan", pnote->to_list))
    return TRUE;
  if (IS_IMMORTAL (ch) && is_name ("immortal", pnote->to_list))
    return TRUE;
  if (is_name (NAME (ch), pnote->to_list))
    return TRUE;
  if (LEVEL (ch) >= 110)
    return TRUE;
  return FALSE;
}

void 
note_attach (CHAR_DATA * ch)
{
  NOTE_DATA *pnote;
  check_ced (ch);
  if (ch->ced->pnote != NULL)
    return;
  if (note_free == NULL)
    {
      pnote = mem_alloc (sizeof (*ch->ced->pnote));
    }
  else
    {
      pnote = note_free;
      note_free = note_free->next;
    }
  pnote->next = NULL;
  pnote->sender = str_dup (NAME (ch));
  pnote->date = str_dup ("");
  pnote->to_list = str_dup ("");
  pnote->subject = str_dup ("");
  pnote->text = str_dup ("");
  pnote->lines = 0;
  ch->ced->pnote = pnote;
  return;
}

void 
note_remove (CHAR_DATA * ch, NOTE_DATA * pnote)
{
  char to_new[SML_LENGTH];
  char to_one[SML_LENGTH];
  FILE *fp;
  NOTE_DATA *prev;
  char *to_list;
/*
   * Build a new to_list.
   * Strip out this recipient.
 */
  to_new[0] = '\0';
  to_list = pnote->to_list;
  while (*to_list != '\0')
    {
      to_list = one_argy (to_list, to_one);
      if (to_one[0] != '\0' && str_cmp (NAME (ch), to_one))
	{
	  strcat (to_new, " ");
	  strcat (to_new, to_one);
	}
    }
/*
   * Just a simple recipient removal?
 */
  if (LEVEL (ch) < 110 && !is_note_to (ch, pnote))
    {
      if (str_cmp (NAME (ch), pnote->sender) && to_new[0] != '\0')
	{
	  free_string (pnote->to_list);
	  pnote->to_list = str_dup (to_new + 1);
	  return;
	}
    }
/*
   * Remove note from linked list.
 */
  if (pnote == note_list)
    {
      note_list = pnote->next;
    }
  else
    {
      for (prev = note_list; prev != NULL; prev = prev->next)
	{
	  if (prev->next == pnote)
	    break;
	}
      if (prev == NULL)
	{
	  bug ("Note_remove: pnote not found.", 0);
	  return;
	}
      prev->next = pnote->next;
    }
  free_string (pnote->text);
  free_string (pnote->subject);
  free_string (pnote->to_list);
  free_string (pnote->date);
  free_string (pnote->sender);
  pnote->next = note_free;
  note_free = pnote;
/*
   * Rewrite entire list.
 */
#ifndef WINDOWS
//  fclose (fpReserve);
#endif
  if ((fp = fopen (NOTE_FILE, "w")) == NULL)
    {
      perror (NOTE_FILE);
    }
  else
    {
      for (pnote = note_list; pnote != NULL; pnote = pnote->next)
	{
	  fprintf (fp, "Sender %s~\n", fix_string (pnote->sender));
	  fprintf (fp, "TBoard %d\n", pnote->board_num);
	  fprintf (fp, "Date %s~\n", pnote->date);
	  fprintf (fp, "Stamp %ld\n", pnote->date_stamp);
	  fprintf (fp, "To %s~\n", fix_string (pnote->to_list));
	  fprintf (fp, "Subject %s~\n", fix_string (pnote->subject));
	  fprintf (fp, "Text\n%s~\n", fix_string (pnote->text));
	  fprintf (fp, "End\n");
	}
      fclose (fp);
    }
#ifndef WINDOWS
//  fpReserve = fopen (NULL_FILE, "r");
#endif
  return;
}

void 
do_note (CHAR_DATA * ch, char *argy)
{
  char buf[STD_LENGTH * 17];
  char buf1[STD_LENGTH * 17];
  char arg[SML_LENGTH];
  NOTE_DATA *pnote;
  int vnum;
  int board_here;		/*Boards and board nums by Owen Emlen */
  SINGLE_OBJECT *obj;
  int anum;
  DEFINE_COMMAND ("note", do_note, POSITION_DEAD, 0, LOG_NORMAL, "This command is used to post/read/remove notes.")

    if (IS_MOB (ch))
    return;
  board_here = 0;
  obj = get_obj_here (ch, "board", SEARCH_ROOM_FIRST);
  if (obj == NULL)
    {
      board_here = 1;
    }
  else
    board_here = obj->pIndexData->value[9];
  buf1[0] = '\0';
  argy = one_argy (argy, arg);
  smash_tilde (argy);
  if (arg[0] == '\0')
    {
      do_note (ch, "read");
      return;
    }
  if (!str_cmp (arg, "list"))
    {
      vnum = 0;
      sprintf(buf1,"\x1B[34;1m------------------------------------------------------------------------\x1B[37;0m\n\r");
      sprintf(buf1+strlen(buf1),"\x1B[36;1m New  ###  Sender/From         Subject\x1B[37;0m\n\r");
      sprintf(buf1+strlen(buf1),"\x1B[34;1m------------------------------------------------------------------------\x1B[37;0m\n\r");

      for (pnote = note_list; pnote != NULL; pnote = pnote->next)
	{
	  if (is_note_to (ch, pnote) &&
	      (board_here == pnote->board_num || IS_IMMORTAL (ch)))
	    {
		  if (strlen(pnote->subject)>35) {
			pnote->subject[35]='\0';
			}
	      sprintf (buf, "%s \x1B[37;1m%3d\x1B[37;0m  From \x1B[35;1m%-14s\x1B[37;0m '\x1B[37;1m%s\x1B[37;0m'\n\r",
		       (pnote->date_stamp > ch->pcdata->last_note
			&& str_cmp (pnote->sender, NAME (ch))) ? "\x1B[34;1m(New)\x1B[37;0m" : "     ",
		       vnum,
		pnote->sender, pnote->subject);
	      strcat (buf1, buf);
	      vnum++;
	    }
	  else
	    vnum++;
	  if (strlen (buf1) > (STD_LENGTH * 16))
	    {
	      strcat (buf1, "\n\rTOO MANY NOTES.. WAIT UNTIL A GOD REMOVES SOME!\n\r");
	      break;
	    }
	}
      page_to_char (buf1, ch);
      return;
    }
  if (!str_cmp (arg, "read"))
    {
      bool fAll;
      if (!str_cmp (argy, "all"))
	{
	  fAll = TRUE;
	  anum = 0;
	}
      else if (argy[0] == '\0' || !str_prefix (argy, "next"))
	/* read next unread note */
	{
	  vnum = 0;
	  for (pnote = note_list; pnote != NULL; pnote = pnote->next)
	    {
	      if (is_note_to (ch, pnote) &&
		  (board_here == pnote->board_num || IS_IMMORTAL (ch))
		  && str_cmp (NAME (ch), pnote->sender)
		  && ch->pcdata->last_note < pnote->date_stamp)
		{
		  sprintf (buf,"\x1B[33;1m---------------------------------------------------------------------------\x1B[37;0m\n\r");
		  sprintf (buf+strlen(buf), "[Note #\x1B[37;1m%d:%d\x1B[37;0m] From: \x1B[35;1m%s\x1B[37;0m  To: \x1B[35;1m%s\x1B[37;0m\n\r",
			   vnum,
			   pnote->board_num,
			   pnote->sender,
			   pnote->to_list);
		  if (strlen(pnote->subject)>35) {
			pnote->subject[35]='\0';
			}
		  sprintf (buf+strlen(buf),"%s.  Subject: \x1B[37;1m%s\x1B[37;0m\n\r",
			   pnote->date,
			   pnote->subject);
		  sprintf (buf+strlen(buf),"\x1B[33;1m---------------------------------------------------------------------------\x1B[37;0m\n\r");
		  strcat (buf1, buf);
		  strcat (buf1, pnote->text);
		  ch->pcdata->last_note = UMAX (ch->pcdata->last_note, pnote->date_stamp);
		  page_to_char (buf1, ch);
		  return;
		}
	      else
		vnum++;
	    }
	  send_to_char ("You have no unread notes.\n\r", ch);
	  return;
	}
      else if (is_number (argy))
	{
	  fAll = FALSE;
	  anum = atoi (argy);
	}
      else
	{
	  send_to_char ("Note read which number?\n\r", ch);
	  return;
	}
      vnum = 0;
      for (pnote = note_list; pnote != NULL; pnote = pnote->next)
	{
	  if ((vnum++ == anum || fAll) && is_note_to (ch, pnote) &&
	      (board_here == pnote->board_num || IS_IMMORTAL (ch)))
	    {
		  sprintf (buf,"\x1B[33;1m---------------------------------------------------------------------------\x1B[37;0m\n\r");
		  sprintf (buf+strlen(buf), "[Note #\x1B[37;1m%d:%d\x1B[37;0m] From: \x1B[35;1m%s\x1B[37;0m  To: \x1B[35;1m%s\x1B[37;0m\n\r",
			   vnum - 1,
			   pnote->board_num,
			   pnote->sender,
			   pnote->to_list);
		  if (strlen(pnote->subject)>35) {
			pnote->subject[35]='\0';
			}
		  sprintf (buf+strlen(buf),"Dated %s.  Subject: \x1B[37;1m%s\x1B[37;0m\n\r",
			   pnote->date,
			   pnote->subject);
		  sprintf (buf+strlen(buf),"\x1B[33;1m---------------------------------------------------------------------------\x1B[37;0m\n\r");
	      strcat (buf1, buf);
	      strcat (buf1, pnote->text);
	      page_to_char (buf1, ch);
	      return;
	    }
	}
      send_to_char ("No such note.\n\r", ch);
      return;
    }
  if (!str_cmp (arg, "write"))
    {
      if (LEVEL (ch) < 100 && board_here == 1)
	{
	  send_to_char ("You can't write on the immortal notice board.\n\r", ch);
	  return;
	}
      check_ced (ch);
      note_attach (ch);
      string_append (ch, &ch->ced->pnote->text);
      return;
    }
  if (!str_cmp (arg, "fwrite"))
    {
      if (LEVEL (ch) < 100 && board_here == 1)
	{
	  send_to_char ("You can't write on the immortal notice board.\n\r", ch);
	  return;
	}
      check_ced (ch);
      note_attach (ch);
      fullscreen_editor (ch, &ch->ced->pnote->text);
      return;
    }
  if (!str_cmp (arg, "+"))
    {
      check_ced (ch);
      note_attach (ch);
      strcpy (buf, ch->ced->pnote->text);
      if (strlen (buf) + strlen (argy) >= STD_LENGTH - 200)
	{
	  send_to_char ("Note too long.\n\r", ch);
	  return;
	}
      strcat (buf, argy);
      strcat (buf, "\n\r");
      free_string (ch->ced->pnote->text);
      ch->ced->pnote->text = str_dup (buf);
      ch->ced->pnote->lines += 1;
      send_to_char ("Ok.\n\r", ch);
      return;
    }
  if (!str_cmp (arg, "-"))
    {
      int num, cnt;
      char new_buf[STD_LENGTH];
      const char *str;
      check_ced (ch);
      if (ch->ced->pnote == NULL)
	{
	  send_to_char ("You have to start a note first.\n\r", ch);
	  return;
	}
      if (ch->ced->pnote->lines == 0)
	{
	  send_to_char ("Nothing to delete.\n\r", ch);
	  return;
	}
      new_buf[0] = '\0';
      str = ch->ced->pnote->text;
      cnt = 1;
      for (num = 1; num <= ch->ced->pnote->lines; num++)
	{
	  while (*str != '\r' && *str != '\0')
	    {
	      ++str;
	      ++cnt;
	    }
	}
      strncpy (new_buf, ch->ced->pnote->text, cnt);
      new_buf[cnt] = '\0';
      free_string (ch->ced->pnote->text);
      ch->ced->pnote->text = str_dup (new_buf);
      ch->ced->pnote->lines -= 1;
      send_to_char ("Ok.\n\r", ch);
      return;
    }
  if (!str_cmp (arg, "subject"))
    {
      check_ced (ch);
      note_attach (ch);
      free_string (ch->ced->pnote->subject);
      ch->ced->pnote->subject = str_dup (argy);
      send_to_char ("Ok.\n\r", ch);
      return;
    }
  if (!str_cmp (arg, "to"))
    {
      check_ced (ch);
      note_attach (ch);
      free_string (ch->ced->pnote->to_list);
      ch->ced->pnote->to_list = str_dup (argy);
      send_to_char ("Ok.\n\r", ch);
      return;
    }
  if (!str_cmp (arg, "clear"))
    {
      check_ced (ch);
      if (ch->ced->pnote != NULL)
	{
	  free_string (ch->ced->pnote->text);
	  free_string (ch->ced->pnote->subject);
	  free_string (ch->ced->pnote->to_list);
	  free_string (ch->ced->pnote->date);
	  free_string (ch->ced->pnote->sender);
	  ch->ced->pnote->next = note_free;
	  note_free = ch->ced->pnote;
	  ch->ced->pnote = NULL;
	}
      send_to_char ("Ok.\n\r", ch);
      return;
    }
  if (!str_cmp (arg, "show"))
    {
      check_ced (ch);
      if (ch->ced->pnote == NULL)
	{
	  send_to_char ("You have no note in progress.\n\r", ch);
	  return;
	}
      sprintf (buf, "%s: %s\n\rTo: %s\n\rLines: %d\n\r",
	       ch->ced->pnote->sender,
	       ch->ced->pnote->subject,
	       ch->ced->pnote->to_list,
	       ch->ced->pnote->lines
	);
      strcat (buf1, buf);
      strcat (buf1, ch->ced->pnote->text);
      page_to_char (buf1, ch);
      return;
    }
  if (!str_cmp (arg, "post") || !str_prefix (arg, "send"))
    {
      FILE *fp;
      char *strtime;
      check_ced (ch);
      if (ch->ced->pnote == NULL)
	{
	  send_to_char ("You have no note in progress.\n\r", ch);
	  return;
	}
      if (board_here == 1 && LEVEL (ch) < 100)
	{
	  send_to_char ("This board is reserved for immortals posting messages to mortals.\n\r", ch);
	  send_to_char ("Please post on a public board if you wish to write a note.\n\r", ch);
	  return;
	}
      if (!str_cmp (ch->ced->pnote->to_list, ""))
	{
	  send_to_char (
	    "You need to provide a recipient (name, all, or immortal).\n\r",
			 ch);
	  return;
	}
      if (!str_cmp (ch->ced->pnote->subject, ""))
	{
	  send_to_char ("You need to provide a subject.\n\r", ch);
	  return;
	}
      ch->ced->pnote->next = NULL;
      strtime = ctime (&current_time);
      strtime[strlen (strtime) - 1] = '\0';
      ch->ced->pnote->board_num = board_here;
      ch->ced->pnote->date = str_dup (strtime);
      ch->ced->pnote->date_stamp = current_time;
      if (note_list == NULL)
	{
	  note_list = ch->ced->pnote;
	}
      else
	{
	  for (pnote = note_list; pnote->next != NULL; pnote = pnote->next)
	    ;
	  pnote->next = ch->ced->pnote;
	}
      pnote = ch->ced->pnote;
      ch->ced->pnote = NULL;
#ifndef WINDOWS
//      fclose (fpReserve);
#endif
      if ((fp = fopen (NOTE_FILE, "a")) == NULL)
	{
	  perror (NOTE_FILE);
	}
      else
	{
	  fprintf (fp, "Sender %s~\n", fix_string (pnote->sender));
	  fprintf (fp, "TBoard %d\n", pnote->board_num);
	  fprintf (fp, "Date %s~\n", pnote->date);
	  fprintf (fp, "Stamp %ld\n", pnote->date_stamp);
	  fprintf (fp, "To %s~\n", fix_string (pnote->to_list));
	  fprintf (fp, "Subject %s~\n", fix_string (pnote->subject));
	  fprintf (fp, "Text\n%s~\n", pnote->text);
	  fprintf (fp, "End\n\n");
	  fclose (fp);
	}
#ifndef WINDOWS
//      fpReserve = fopen (NULL_FILE, "r");
#endif
      send_to_char ("Ok.\n\r", ch);
      return;
    }
  if (!str_cmp (arg, "remove"))
    {
      if (!is_number (argy))
	{
	  send_to_char ("Note remove which number?\n\r", ch);
	  return;
	}
      anum = atoi (argy);
      vnum = 0;
      for (pnote = note_list; pnote != NULL; pnote = pnote->next)
	{
	  if (vnum++ == anum && (
				  (is_note_to (ch, pnote) && !is_name ("all", pnote->to_list)) || LEVEL (ch) > 109))
	    {
	      note_remove (ch, pnote);
	      send_to_char ("Ok.\n\r", ch);
	      return;
	    }
	}
      send_to_char ("No such note.\n\r", ch);
      return;
    }
  send_to_char ("Huh? Type 'help note' for usage.\n\r", ch);
  return;
}