package baf.guide;
import java.io.*;
import java.util.*;
import baf.util.*;
import javax.servlet.*;
import javax.servlet.http.*;
/** Items form the core of the Guide.  Subclasses include Game, Author,
 *  and so on - anything that has its own page and can serve as the
 *  basis of an index.  Items are customarily read from a text file
 *  marked up with lines beginning with colons in a manner that I
 *  really should document somewhere.
 */
public abstract class Item implements Comparable {
  static final String basedir = "/home/httpd/html/if/raw";
  static final String baseurl = "/if/data/items";
  public String filename;
  public String url;
  public String rawname;
  public String name;
  static String toc = "/if/index.html";
  protected String sortString = null;
  long lastModified = 0;
  Properties attributes = new Properties();
  public static String nameToUrl(String s) {
    s = s.replace(' ', '_');
    if (s.indexOf(';') != -1) s = s.replace(';', ',');
    if (s.indexOf('&') != -1) s = s.replace('&', '+');
    //  There are several other unsafe characters, but they're
    //  unlikely to be used.
    //  '&' *should* be a safe character, but isn't.
    return s;
  }
  public static String urlToName(String s) {
    s = s.replace('_', ' ');
    if (s.indexOf(',') != -1) s = s.replace(',', ';');
    if (s.indexOf('+') != -1) s = s.replace('+', '&');
    return s;
  }
  static Hashtable byPath = new Hashtable();
  public static synchronized Item forPath(String path) throws IOException {
    Item item = (Item)byPath.get(path);
    // If it's out of date, forget you ever saw it.
    if (item != null) {
      File f = new File(basedir+path);
      if (f.lastModified() > item.lastModified) item = null;
    }
    if (item == null) {
      if (path.startsWith("/games/")) item = new Game(path);
      else if (path.startsWith("/authors/")) item = new Author(path);
      else if (path.startsWith("/years/")) item = new Year(path);
      else if (path.startsWith("/devsys/")) item = new Devsys(path);
      else if (path.startsWith("/platforms/")) item = new Platform(path);
      else if (path.startsWith("/genres/")) item = new Genre(path);
      else if (path.startsWith("/lingvoj/")) item = new Language(path);
      else if (path.startsWith("/ratings/")) item = new Rating(path);
      else if (path.startsWith("/chron/")) item = new Chron(path);
      else throw new IllegalArgumentException();
      byPath.put(path, item);
    }
    return item;
  }
  /** Creates a new Item.  
   *  @param path The (relative) path to the data file
   */
  public Item(String path) throws IOException {
    rawname = path.substring(path.indexOf('/', 1)+1);
    name = urlToName(rawname);
    sortString = name.toLowerCase();
    filename = basedir + path;
    url = baseurl + path;
    try {
      lastModified = new File(filename).lastModified();
      BufferedReader f = new BufferedReader(new FileReader(filename));
      String line;
      while ((line = f.readLine()) != null) {	
	if (line.length() > 0 && line.charAt(0) == ':') {
	  char c = line.charAt(1);
	  if (!Character.isWhitespace(c)) {
	    StringTokenizer st = new StringTokenizer(line);
	    String tag = st.nextToken();
	    String value = st.nextToken("").trim();
	    // Chron tags get parsed specially
	    if (c == 'c') {
	      StringTokenizer dt = new StringTokenizer(value, "/ ");
	      String month = dt.nextToken();
	      String day = dt.nextToken();
	      String year = dt.nextToken();
	      value = year + ((month.length()==1)? ".0" : ".") + month;
	    }
	    attributes.put(tag, value);
	  }
	}
      }
      f.close();
    } catch (FileNotFoundException e) {
      // It's OK to not have a data file.  It just means that this is a blank
      // item, existing solely because of references from other items.
      // (ie, an Author with no contact info).
    }
  }
  public String toString() {
    return name;
  }
  /** Returns a string suitable for displaying in an alphabetical index.
   */
  public String getListingString() {
    return toString();
  }
  /** Returns the key by which this Item is referred to in files
   */
  public String getRefString() {
    return name;
  }
  /** Returns a string suitable for alphabetical comparisons.
   */
  public final String getSortString() {
    return sortString;
  }
  /** The method for the "Comparable" interface
   */
  public int compareTo(Object o) {
    Item i = (Item)o;
    return getSortString().compareTo(i.getSortString());
  }
  /** Crucial! Crucial!
   */
  public boolean equals(Object o) {
    return o != null && o instanceof Item &&
      ((Item)o).filename.equals(filename);
  }
  /** This may be used by the servlet's getLastModified method.
   */
  public long getLastModified() throws IOException {
    Game.update();
    if (lastModified >= Game.globalLastModified) return lastModified;
    else return Game.globalLastModified;
  }
  /** Returns the URL for the page detailing this Item
   */
  public String getURL() {
    return url;
  }
  /** Inserts a hotlink in the output stream.
   *  @param out The output stream
   *  @param loc The URL to link to
   *  @param txt The visible text of the hotlink
   */
  protected static void hotlink(ServletOutputStream out, String loc, String txt)
    throws IOException {
    out.print("");
    out.print(txt);
    out.print("");
  }
  /** Insterts into the output stream a link to this item.
   */
  void hotlink(ServletOutputStream out, String txt) throws IOException {
    hotlink(out, url, txt);
  }
  /** Inserts into the output stream a link to this item.
   *  Uses the item's name as the visible text.
   */
  void hotlink(ServletOutputStream out) throws IOException {
    hotlink(out, url, name);
  }
  /** Prints a standard beginning to HTML pages in the Guide.
   */
  public static final void header(ServletOutputStream out,
    String title, String desc, Index index, Item current) throws IOException {
    out.print("\n");
    out.print(title);
    out.print("\n\n");
    if (index != null) {
      out.print("\n");
    }
    out.print("");
    navigation(out, index, current);
    out.print("
\n");
  }
  public static final void header(ServletOutputStream out,
    String title, String desc) throws IOException {
    header(out, title, desc, null, null);
  }
  public void header(ServletOutputStream out) throws IOException {
    header(out, name, getDescription(), Index.forTag(getTag()), this);
  }
  /** Prints a standard ending to HTML pages in the Guide.
   */
  public static final void footer(ServletOutputStream out) throws IOException {
    out.print("\n
\nBaf's Guide to the Interactive Fiction Archive
\n");
    out.print("Copyright © 1998 ");
    hotlink(out, "http://www.wurb.com/~carl/", "Carl Muckenhoupt");
    out.print(" - ");
    hotlink(out, "mailto:carl@wurb.com", "carl@wurb.com");
    out.print("