/* Time-stamp: <97/01/23 13:44:35 john> */

/* 
# Purpose: does much of the work for the program in <a href="#editor.c">editor.c</a>
 */

#include <stdio.h>
#include <ctype.h>
#include "attr.h"
#include "style.h"		/* required by readattr.h and misc.h */
#include "misc.h"
#include "cgi.h"
#include "readattr.h"
#include "putedit.h"

#define debug 0
/* #define debugging 1 */

static int check_always_OK(struct entry *new_entry, int entry_count)
{
  return 1;
}

/* Not working yet:
   look for likely corruption in a list of entries
   */

static void vet_entries(struct entry *entries,
			int debug_vetting)
{
  struct entry *entry;

  if (debug_vetting)
    {
      printf("<h2>Vetting new entries</h2><pre>\n");
    }
  for (entry = entries;
       entry != NULL;
       entry = entry->next)
    {
      struct attribute *attr; 
      for (attr = entry->attributes;
	   attr != NULL;
	   attr = attr->next)
	{
	  char *key = attr->key;
	  char *value = attr->value;
	  struct entry *vetter = NULL;
	  int got_some;
	  if (debug_vetting)
	    {
	      printf("Vetting %s=\"%s\"\n", key, value);
	    }
#if 0
	  got_some = read_attributes_string_or_stream(value,
						      NULL,
						      &vetter,
						      check_always_OK,
						      0);
	  if (got_some || (vetter != NULL))
	    {
	      printf("%s appears to have some more key-value pairs inside it!\n", key);
	      free_entries(vetter);
	    }
#endif
	}
    }
  if (debug_vetting)
    {
      printf("</pre>\n");
    }
}

static int add_dummy(struct entry *this_entry,
		     struct entry **new_entry_return,
		     char *direction)
{
  int i;
  char *string;
  char dummybuf[1024];
  struct entry *new_entry = (struct entry*)malloc(sizeof(struct entry));
  if (new_entry == NULL) return 0;

  new_entry->inclusions_included = 0;

  string = (char*)malloc(strlen("dummy")+1);

  if (string == NULL)
    {
      Free(new_entry);
      return 0;
    }
  strcpy(string, "dummy");
  new_entry->type = string;

  sprintf(dummybuf, "dummy%x", string);
  string = (char*)malloc(strlen(dummybuf)+1);

  if (string == NULL)
    {
      Free(new_entry->type);
      Free(new_entry);
      return 0;
    }

  strcpy(string, dummybuf);
  new_entry->name = string;

  new_entry->grid = this_entry->grid;
  new_entry->column = this_entry->column;
  new_entry->left = this_entry->left;
  new_entry->top = this_entry->top + 1;
  new_entry->width = 1;
  new_entry->height = 1;
  new_entry->max_height = MAX_MAX_HEIGHT;

  new_entry->attributes = NULL;

  if ((!set_attr(new_entry, "type", "dummy")) ||
      (!set_attr(new_entry, "name", dummybuf)) ||
      (!set_attr(new_entry, "status", "new")) ||
      (!set_attr(new_entry, "direction", direction)) ||
      (!set_attr(new_entry, "above-me", this_entry->name))
      )
    {
      free_entries(new_entry);
      return 0;
    }

  new_entry->next = this_entry->next;
  this_entry->next = new_entry;

  *new_entry_return = new_entry;

  return 1;
}

static void style_field_from_attrs(struct entry *entry, char *field_name)
{
  char *field_value = extract_attr(entry, field_name);
  if (field_value != NULL)
    {
      printf("&%s=%s", field_name, field_value);
    }
}

static void continuation_link(struct entry *from_form,
			      char *pagetype,
			      char *pagename,
			      char *visible,
			      char *extra_key,
			      char *extra_value)
{
  printf("[<a href=\"getplan.cgi?");
  printf("name=%s", pagename);
  printf("&type=%s", pagetype);
  style_field_from_attrs(from_form, "output");
  style_field_from_attrs(from_form, "zoom");
  style_field_from_attrs(from_form, "graphics");
  style_field_from_attrs(from_form, "detail");
  style_field_from_attrs(from_form, "pictures");
  style_field_from_attrs(from_form, "debug");
  style_field_from_attrs(from_form, "verbose");
  style_field_from_attrs(from_form, "unvetted");
  if ((extra_key != NULL) && (extra_value != NULL))
    {
      printf("&%s=%s", extra_key, extra_value);
    }
  printf("&muckthecache=%d", getpid());
  printf("\">%s</a>]\n", visible);
}

static int edit(struct attribute *attrs,
		int mode)
{
  int read_error = READ_OK;
  struct entry from_form;
  struct entry *from_edit = NULL;
  from_form.next = NULL;
  from_form.column = 0;
  from_form.left = 0;
  from_form.width = 0;
  from_form.height = 0;
  from_form.name = "Dummy entry from form";
  from_form.type = "Dummy entry";
  from_form.attributes = attrs;

  {
    char *pagetype = extract_attr(&from_form, "pagetype");
    char *pagename = extract_attr(&from_form, "pagename");
    char *entryname = extract_attr(&from_form, "entryname");
    char *editor = extract_attr(&from_form, "editor");
    char *password = extract_attr(&from_form, "password");
    char *attribute_data = extract_attr(&from_form, "attribute_data");

    char *graphics = extract_attr(&from_form, "graphics");
    char *detail = extract_attr(&from_form, "detail");
    char *pictures = extract_attr(&from_form, "pictures");
    char *unvetted = extract_attr(&from_form, "unvetted");

    int new_data_error = READ_OK;

    if (debug)
      {
	printf("Pagetype=\"%s\"<br>\n", pagetype ? pagetype : "missing");
	printf("Pagename=\"%s\"<br>\n", pagename ? pagename : "missing");
	printf("Entryname=\"%s\"<br>\n", entryname ? entryname : "missing");
	printf("Editor=\"%s\"<br>\n", editor ? editor : "missing");
	printf("Password=\"%s\"<br>\n", password ? password : "missing");
	printf("Attribute_data=\"%s\"<br>\n", attribute_data ? attribute_data : "missing");
      }

    if (attribute_data != NULL)
      {
	if (!read_attributes_string_or_stream(attribute_data, NULL,
					      &from_edit,
					      &new_data_error,
					      default_check_entry, 1, debug))
	  {
	    printf("Could not parse attribute data field from edit request\n");
	    return 0;
	  }
      } else {
	if (debug) printf("No attribute data from which to read\n");
      }

    if (debug)
      {
	printf("Here is what's left from the form:\n");
	show_entries(&from_form);
	printf("Here is what we got from the edit field:\n");
	show_entries(from_edit);
      }

    vet_entries(&from_form, 0);
    vet_entries(from_edit, 0);

    {
      struct entry *old_entries = NULL;
      struct entry *this_entry;
      struct entry *prev_entry;
      int is_layout = 0;
     
      if (!read_data(pagetype, pagename,
		     &old_entries, &read_error,
		     default_check_entry, 1, 1, 0))
	{
	  printf("<p>Problem reading attributes from %ss/%s to merge new ones, trying again with debug on so you can see where the problem is</p>\n",
		 pagetype, pagename);
#if 1
	  if (!read_data(pagetype, pagename,
			 &old_entries, &read_error,
			 default_check_entry, 1, 1, 1))
	    {
	      printf("<p>Problem reading attributes from %ss/%s to merge new ones</p>\n",
		     pagetype, pagename);
	      report_read_error(read_error, pagetype, pagename);
	    }
#endif
	  free_entries(from_edit);
	  return 0;
	}

      prev_entry = old_entries; /* not that they should have a chance
				   to delete the first entry, from the
				   form, andyway! */

      for (this_entry = old_entries;
	   this_entry != NULL;
	   this_entry = this_entry->next)
	{
	  char *old_name;

	  if (strcmp(this_entry->name, entryname) == 0)
	    {
	      if (debug)
		{
		  printf("Got it (on name)!\n");
		}
	      break;
	    }

	  old_name = get_attr(this_entry, "old-name");

	  if ((old_name != NULL) &&
	      (strcmp(old_name, entryname) == 0))
	    {
	      if (debug)
		{
		  printf("Got it (on old-name)!\n");
		}
	      break;
	    }



	  prev_entry = this_entry;
	}

      if (this_entry == NULL)
	{
	  printf("Could not find entry to edit\n");
	  return 0;
	}

      switch (mode)
	{
	case EDIT_MODIFY_LAYOUT:
	  is_layout = 1;
	case EDIT_MODIFY:
	  merge_entries(this_entry, from_edit);
	  merge_entries(this_entry, &from_form);
	  if (1 || is_layout)
	    {
	      hack_layout_data(this_entry);
	    }
	  if (debug)
	    {
	      printf("About to save\n");
	    }
	  save_edits(old_entries, this_entry,
		     pagetype, pagename,
		     editor, password,
		     "edit-requests", "new-edits");
	  break;
	case EDIT_DELETE:
	  prev_entry->next = this_entry->next;
	  this_entry->next = NULL;
	  set_attr(this_entry, "status", "deleted");
	  save_edits(old_entries, this_entry,
		     pagetype, pagename,
		     editor, password,
		     /* a deletion is just an edit to status=deleted: */
		     "edit-requests", "new-edits");
	  free_entries(this_entry);
	  break;
	case EDIT_ADDENTRY:
	  {
	    struct entry *new_entry = NULL;
#if 1
	    if (!add_dummy(this_entry,
			   &new_entry,
			   ((this_entry->column == 0) ? "ahead" :
			    (this_entry->column < 0) ? "left" : "right")))
	      return 0;
#endif
#if 0
	    printf("<p>Made dummy</p>\n");
	    printf("</body></html>\n");
	    exit(0);
#endif
#if 1
	    save_edits(old_entries, new_entry,
		       pagetype, pagename,
		       editor, password,
		       "edit-requests", "new-entries");
#endif
	  }
	  break;
	}

      free_entries(from_edit);

    }
    printf("<br><hr>\n");
    continuation_link(&from_form,
		      pagetype, pagename,
		      "View edited page",
		      NULL, NULL);
    continuation_link(&from_form,
		      pagetype, pagename,
		      "View edited page (with edit links)",
		      "all-edit-links", "on");
    continuation_link(&from_form,
		      pagetype, pagename,
		      "Continue to edit (en masse -- bulky)",
		      "edit", "on");
    continuation_link(&from_form,
		      pagetype, pagename,
		      "Debug edited page",
		      "debug", "on");
  }

  return 1;
}

int modify(struct attribute *attrs)
{
  return edit(attrs, EDIT_MODIFY);
}

int addentry(struct attribute *attrs)
{
  return edit(attrs, EDIT_ADDENTRY);
}

int delentry(struct attribute *attrs)
{
  return edit(attrs, EDIT_DELETE);
}

int addpage(struct attribute *attrs)
{
  struct entry from_form;
  struct entry *from_edit = NULL;
  from_form.next = NULL;
  from_form.column = 0;
  from_form.left = 0;
  from_form.width = 0;
  from_form.height = 0;
  from_form.name = "Dummy entry from form";
  from_form.type = "Dummy entry";
  from_form.attributes = attrs;
  {
    char *pagename = get_attr(&from_form, "name");
    char *filename;
    if (pagename == NULL)
      {
	return 0;
      } else {
	char *filename = (char*)malloc(strlen(pagename)+strlen("../roads/.attr0"));

	if (filename == NULL)
	  {
	    return 0;
	  } else {
	    char *s;
	    int n;
	    int i;
	    sprintf(filename, "../roads/%s.attr", pagename);
	    n = strlen(filename)-strlen(".attr");

	    for (i = strlen("../roads/"); i < n; i++)
	      {
		char c = filename[i];
		if (('A' <= c) && (c <= 'Z'))
		  {
		    filename[i] = c + ('a' - 'A');
		  } else {
		    if (!(('a' <= c) && (c <= 'z')))
		      {
			filename[i] = '-';
		      }
		  }
	      }

	    if (debug) printf("Made filename into %s\n", filename);

	    {
	      int i;
	      struct entry *new_page = (struct entry *)malloc(sizeof(struct entry));
	      struct entry *dummies = new_page;
	      
	      if (new_page == NULL)
		{
		  Free(filename);
		  return 0;
		}

	      new_page->next = NULL;
	      new_page->grid = NULL;
	      new_page->column = 0;
	      new_page->type = "road";
	      new_page->name = pagename;
	      new_page->left = 0;
	      new_page->top = 0;
	      new_page->width = 1;
	      new_page->height = 1;
	      new_page->max_height = MAX_MAX_HEIGHT;
	      new_page->attributes = NULL;
	      new_page->inclusions_included = 0;

	      if ((!set_attr(new_page, "type", "road")) ||
		  (!set_attr(new_page, "name", pagename)) ||
		  (!set_attr(new_page, "status", "new")))
		{
		  free_entries(new_page);
		  return 0;
		}

	      add_dummy(dummies, & dummies, "ahead");

	      for (i = 0; i < 50; i++)
		{
		  add_dummy(dummies, &dummies, "left");
		  add_dummy(dummies, &dummies, "right");
		}

	      add_dummy(dummies, & dummies, "ahead");

	      
	      {
		char *editor = get_attr(&from_form, "editor");

		printf("<p>Editor \"%s\" made page \"%s\" in file \"%s\"</p>\n",
		       editor, pagename, filename);
	      
		save_edits(new_page, new_page,
			   filename,
			   editor, get_attr(&from_form, "password"), "");
	      }
	    }
	  }
      }
  }
}


/* end of putedit.c */
