/* Time-stamp: <97/01/24 14:41:05 john> */

#include <stdio.h>
#include "attr.h"
#include "grid.h"
#include "style.h"
#include "edit.h"
#include "graphics.h"

/*
# Purpose: This file outputs edit forms for entries, with the appropriate fields for each type and kind of entry.
 */

/* Things to do:
   - strip out specially handled fields from general attributes box
   - checkbox for row="next"?
 */

void output_attributes(struct entry *entry, int with_help)
{
  struct attribute *attr;

  for (attr = entry->attributes;
       attr != NULL;
       attr = attr->next)
    {
      char *s = attr->value;
      char c;
      printf(with_help ?
	     "      <a href=\"../doc/authoring/field-types.html#%s\">%s</a>=\"" :
	     "%s=\"", 
	     attr->key, attr->key);
      while ((c = *s++) != '\0')
	{
	  switch (c) {		/* fputs to stdout != puts (concerning */
				/* newline at end) */
	  case '<': fputs("&lt;", stdout); break;
	  case '>': fputs("&gt;", stdout); break;
	  case '\"': fputs("&quot", stdout); break;
	  default:
	    putchar(c);
	    break;
	  }
	}
      printf("\"\n");
    }
}

/* Make an edit text field for one attribute, filled in with its old
   value if any, and a link to the documentation for that attribute.
*/

static void field_for_attribute(struct entry *entry, char *field)
{
  char *old_value = get_attr(entry, field);
  printf("      <a href=\"../doc/authoring/field-types.html#%s\">%s</a>:",
	 field, field);
  printf(" <input type=\"text\" name=\"%s\" value=\"%s\"><br>\n",
	 field, old_value==NULL ? "" : old_value);
}

#define min(_a_,_b_) (((_a_) < (_b_)) ? (_a_) : (_b_))

static void output_choice(char *field_name,
			  char *values_string,
			  char *was_selected)
{
  char *s;
  char c;
  int am_on_name = 1;
  int am_at_line_start = 1;

  int was_selected_length = (was_selected == NULL) ? 0 : strlen(was_selected);
  int remaining_length;

  char *elt_lead_in = "        <li> <input type=\"radio\" name=\"%s\"%s value=\"";
  char *elt_middle = "\">";
  char *elt_run_out = "\n";

  if (values_string == NULL)
    {
      printf("Could not make values selection -- no option list\n");
      return;
    }

  remaining_length = strlen(values_string);

  printf("      <br>Select <a href=\"../doc/authoring/field-types.html#%s\">%s</a>:\n      <ul>\n",
	 field_name, field_name);

  for (s = values_string;
       (c = *s) != '\0';
       s++, remaining_length--)
    {
      if (am_at_line_start)
	{
	  int was_me = ((was_selected_length != 0) &&
			(strncmp(was_selected, s,
				 min(was_selected_length,
				     remaining_length)) == 0));
	  am_at_line_start = 0;
	  printf(elt_lead_in,
		 field_name,
		 was_me ? " selected" : "");
	}

      switch (c)
	{
	case ' ':
	  if (am_on_name)
	    {
	      am_on_name = 0;
	      printf(elt_middle);
	    } else {
	      putchar(c);
	    }
	  break;
	case '\n':
	  am_on_name = 1;
	  am_at_line_start = 1;
	  printf(elt_run_out);
	  break;
	default:
	  putchar(c);
	  break;
	}
    }
  printf(elt_run_out);
  printf("      </ul><br>\n");
}

static void type_selector(struct entry *entry)
{
#if 1
  char *types = get_type_generic_attribute("typelist", "types");
  if (types != NULL)
    {
#if 0
      printf("Got types list\n");
#endif
      output_choice("type", types, entry->type);
    } else {
      field_for_attribute(entry, "type");
    }
#else
  printf("  <a href=\"../doc/authoring/field-types.html#type\">type</a>: <select name=\"type\">\n");
  printf("    <option>cafe\n<option>church\n    <option>company\n    <option selected>dummy\n    <option>educational\n    <option>green\n    <option>leisure-facility\n    <option>medical\n    <option>museum\n    <option>pub\n    <option>public-building\n    <option>restaurant\n    <option>residential\n    <option>road\n    <option>shop\n");
  printf("  </select>\n  <br>\n");
#endif
}

static void kind_field(struct entry *entry, int always)
{
  char *kinds = get_type_generic_attribute(entry->type, "kinds");

  if (kinds != NULL)
    {
      output_choice("kind", kinds, get_attr(entry, "kind"));
    } else {
      if (always)
	{
	  field_for_attribute(entry, "kind");
	}
    }
}

/* Put style fields (see ../doc/tech/getplan-args.html) as hidden
 fields into the form, so that the edit acceptance page can link to
 the edited page with the same style parameters.
 */

static void print_style_fields(struct style *style)
{
  int all_styles = 0;
  printf("      <input type=\"hidden\" name=\"output\" value=\"%s\">\n", style->output_mode);
  if (all_styles || style->graphics) printf("      <input type=\"hidden\" name=\"graphics\" value=\"%s\">\n", style->graphics?"on":"off");
  if (all_styles || style->detail) printf("      <input type=\"hidden\" name=\"detail\" value=\"%s\">\n", style->detail?"on":"off");
  if (all_styles || style->pictures) printf("      <input type=\"hidden\" name=\"pictures\" value=\"%s\">\n", style->pictures?"on":"off");
  if (all_styles || style->debug) printf("      <input type=\"hidden\" name=\"debug\" value=\"%s\">\n", style->debug?"on":"off");
  printf("      <input type=\"hidden\" name=\"unvetted\" value=\"%s\">\n", style->unvetted?"on":"off");
}

/* Make an edit form for an entry. */

void make_edit(struct entry *entry,
	       struct style *style,
	       char *zoomed_to)
{
  char *include;
  int asked_in_particular = 0;
  char *entry_type = entry->type;

  if (style->hide_edit)
    {
      /* We shouldn't really have been called, but let's be safe */
      return;
    }

  printf("\n    <h2>Edit entry ``%s''</h2>\n", entry->name);
#if 0
  printf("<pre>entry->name=\"%s\"\nentry->grid=%#X</pre>",
	 entry->name, entry->grid);
  return;
#endif
  include = get_attr(entry, "include");
  if (include != NULL)
    {
      printf("<p><strong>This entry is only a mention of an entry defined elsewhere.\n");
      printf("What you edit using this form will only change this mention of it.\n");
      printf("To change the main definition, you will have to use a separate form.</strong></p>\n");
      printf("<h2>Edit main definition for %s</h2>\n", entry->name);
      printf("<p>Use");
      printf(" <a href=\"getplan.cgi?type=%s&name=%s&edit=on\">this form</a>",
	     get_attr(entry, "type"), include);
      printf(" to edit the main definition of %s</p>\n", entry->name);
      printf("<h2>Edit this mention of %s</h2>\n", entry->name);
    }
  printf("    <br>\n    <form method=\"post\" action=\"edit.cgi\">\n");

  printf("      <input type=\"hidden\" name=\"pagetype\" value=\"%s\">\n", entry->grid->page_type);
  printf("      <input type=\"hidden\" name=\"pagename\" value=\"%s\">\n", entry->grid->page_name);
  printf("      <input type=\"hidden\" name=\"entryname\" value=\"%s\">\n", entry->name);

  if (zoomed_to != NULL)
    {
      printf("      <input type=\"hidden\" name=\"zoom\" value=\"%s\">\n", zoomed_to);
    }

  print_style_fields(style);

  printf("      Your name (email address) (optional): <input type=\"text\" name=\"editor\"><br>\n");
#ifdef passwording
  printf("      Your password (<a href=\"passwords.html\">if relevant</a>): <input type=\"password\" name=\"password\"><br>\n");
#else
  printf("      <input type=\"hidden\" name=\"password\" value=\"none\">\n");
#endif

  if ((entry->grid != NULL) &&
      (entry->grid->central_entry == entry))
    {
      add_area_layout_exploded_edit(entry);
      field_for_attribute(entry, "postcode");
    }

  if ((strcmp(entry_type, "road") != 0) &&
      (strcmp(entry_type, "green") != 0))
    {
      field_for_attribute(entry, "number");
    }

#if 0
  {
    char *fields_wanted = get_type_generic_attribute(entry->type, "fields-wanted");

    if (fields_wanted != NULL)
      {
#define FIELD_NAME_MAX 100
	char one_field[FIELD_NAME_MAX];

	char *copy_from;
	int copy_to = 0;

	char c;

	for (copy_from = fields_wanted;
	     ((c = *copy_from) != '\0') && (copy_to <= FIELD_NAME_MAX);
	     copy_from++)
	  {
	    switch (c)
	      {
	      case ' ':
		break;
	      case ',':
		one_field[copy_to] = '\0';
		field_for_attribute(entry, one_field);
		copy_to = 0;
		break;
	      default:
		one_field[copy_to++] = c;
		break;
	      }
	  }
	one_field[copy_to] = '\0';
	field_for_attribute(entry, one_field);
      }
    kind_field(entry, 0);
  }
#else

  if ((strcmp(entry_type, "shop")==0) ||
      (strcmp(entry_type, "company")==0) ||
      (strcmp(entry_type, "leisure-facility")==0) ||
      (strcmp(entry_type, "restaurant")==0) ||
      (strcmp(entry_type, "pub")==0) ||
      (strcmp(entry_type, "cafe")==0))
    {
      asked_in_particular = 1;
      kind_field(entry, 1);
      field_for_attribute(entry, "opening-times");
      field_for_attribute(entry, "provides");
      field_for_attribute(entry, "review");
      field_for_attribute(entry, "phone");
    }

  if (strcmp(entry_type, "road")==0)
    {
      char *link = get_attr(entry, "link");
      asked_in_particular = 1;
      if (((link == NULL) || (strlen(link) == 0)) &&
	  ((entry->grid == NULL) ||
	   (entry->grid->central_entry != entry)))
	{
	  printf("      <p>Please fill in the <code>link</code> field so that you can go into this road. If the road does not yet have a data file, trying to follow the link that this creates should take you into a form for making a data file for the road.</p>\n");
	}
      field_for_attribute(entry, "link");
    }

  if (strcmp(entry_type, "educational")==0)
    {
      char *kind = get_attr(entry, "kind");
      asked_in_particular = 1;
      kind_field(entry, 1);
      field_for_attribute(entry, "phone");
      if ((kind != NULL) && (strncmp(kind, "university", 10)==0))
	{
	  field_for_attribute(entry, "home-page");
	} else {
	  field_for_attribute(entry, "variety");
	  printf("<p>Note that <code>variety</code> is more specific than <code>kind</code></p>\n");
	}
    }
	
  if (strcmp(entry_type, "church")==0)
    {
      asked_in_particular = 1;
      field_for_attribute(entry, "event-times");
      kind_field(entry, 1);
      printf("<p>Please use <code>kind</code> for the denomination.</p>\n");
    }
#endif
  if (strcmp(entry_type, "dummy")==0)
    {
      asked_in_particular = 1;

      if (style->verbose)
	{
	  type_selector(entry);
	  field_for_attribute(entry, "name");
	  printf("<p>If you are turning this dummy into a road or a green, please add a <code>link</code> field so that you can go down that road. If the road does not yet have a data file, trying to follow the link that this creates should take you into a form for making a data file for the road. Otherwise, please leave this field blank.</p>\n");
	  field_for_attribute(entry, "link");
	} else {
	  field_for_attribute(entry, "name");
	  type_selector(entry);
	}
    }

  printf("      On left: <input type=\"radio\" name=\"direction\" value=\"left\"%s>\n",
	 entry->column < 0 ? " checked" : "");

  if (entry->column == 0)
    {
      printf("      In middle: <input type=\"radio\" name=\"direction\" value=\"ahead\"%s>\n",
	     entry->column == 0 ? " checked" : "");
    }

  printf("      On right: <input type=\"radio\" name=\"direction\" value=\"right\"%s><br>\n",
	 entry->column > 0 ? " checked" : "");

  if (style->verbose)
    {
      if (asked_in_particular)
	{
	  printf("<p>You can edit other fields in tbe box below, and add new fields. Values in the boxes above will over-ride the corresponding values in the box below.</p>\n");
	} else {
	  printf("<p>You can change any fields in tbe box below, and add new fields.</p>\n");
	}
      printf("      <textarea name=\"attribute_data\" rows=\"4\" cols=\"45\">");
      output_attributes(entry, 0);
      printf("</textarea><br>\n");

      printf("      <p>See the <a href=\"../doc/authoring/format.html\">format documentation</a> for details of what you can put here,\n");
      printf("      and the <a href=\"../doc/authoring/intro.html#edit\">introduction and advice on editing</a> for instructions.</p>\n");
    } else {
      printf("      <p>See the <a href=\"../doc/authoring/intro.html#edit\">introduction and advice on editing</a> for instructions.\n");
      printf("      A <a href=\"getplan.cgi?type=%s&name=%s&edit=on&verbose=on",
	     entry->grid->page_type,
	     entry->grid->page_name);
      if (zoomed_to != NULL)
	{
	  printf("&zoom=%s", zoomed_to);
	}
      printf("\">more powerful version of this edit form</a> is also available, but some people find this daunting.</p>.\n");
    }
  printf("      <input type=\"submit\" value=\"Submit edit\">\n");

  printf("    </form><br>\n");

  if ((style->verbose) &&
      ((entry->grid == NULL) ||
      (entry->grid->central_entry != entry)))
    {
      if (strcmp(entry_type, "dummy") == 0)
	{
	  printf("<hr>\n");
	  printf("    <h2>Delete entry ``%s''</h2>\n", entry->name);
	  printf("    <p>See <a href=\"../doc/authoring/intro.html#delentry\">advice</a> on this.</p>\n");
	  printf("    <br><form method=\"post\" action=\"delete.cgi\">\n");
	  printf("      <input type=\"hidden\" name=\"pagetype\" value=\"%s\">\n", entry->grid->page_type);
	  printf("      <input type=\"hidden\" name=\"pagename\" value=\"%s\">\n", entry->grid->page_name);
	  printf("      <input type=\"hidden\" name=\"entryname\" value=\"%s\">\n", entry->name);
	  print_style_fields(style);
	  printf("      Your name (email address):   <input type=\"text\" name=\"editor\"><br>\n");
#ifdef passwording
	  printf("      Your password (<a href=\"passwords.html\">if relevant</a>): <input type=\"password\" name=\"password\"><br>\n");
#endif
	  printf("      <input type=\"submit\" value=\"Delete entry\">\n");
	  printf("    </form><br>\n");
	}

      printf("<hr>\n");
      printf("    <h2>Add entry below ``%s''</h2>\n", entry->name);
      printf("    <p>See <a href=\"../doc/authoring/intro.html#addentry\">advice</a> on this.</p>\n");
      printf("    <br><form method=\"post\" action=\"addentry.cgi\">\n");
      printf("      <input type=\"hidden\" name=\"pagetype\" value=\"%s\">\n", entry->grid->page_type);
      printf("      <input type=\"hidden\" name=\"pagename\" value=\"%s\">\n", entry->grid->page_name);
      printf("      <input type=\"hidden\" name=\"entryname\" value=\"%s\">\n", entry->name);
      print_style_fields(style);
      printf("      Your name (email address): <input type=\"text\" name=\"editor\"><br>\n");
#ifdef passwording
      printf("      Your password (<a href=\"passwords.html\">if relevant</a>): <input type=\"password\" name=\"password\"><br>\n");
#endif
      printf("      <input type=\"submit\" value=\"Add new entry below\">\n");
      printf("    </form><br><hr>\n");
    }
}

/* end of edit.c */
