/*
 *  PICSLabel.java
 *
 *  Copyright 1997 Massachusetts Institute of Technology.
 *  All Rights Reserved.
 *
 *  Author: Ora Lassila
 *
 *  $Id: PICSLabel.java,v 1.1 1997/04/15 20:39:26 yhchu Exp $
 */
package w3c.www.pics;

import java.util.Dictionary;
import java.util.Hashtable;
import java.util.Date;
import java.util.Vector;
import java.util.Enumeration;
import java.net.URL;
import java.io.PrintStream;
import w3c.tools.sexpr.*;
import w3c.tools.sorter.*;

public class PICSLabel implements SExpr {

  private Symbol version;
  private URL service;
  private Dictionary options;
  private Dictionary ratings;

  public PICSLabel(Symbol version, URL service, Dictionary options)
  {
    this.version = version;
    this.service = service;
    this.options = options;
    this.ratings = new Hashtable();
  }


  public PICSLabel(Symbol version, URL service, Dictionary options,
		   Dictionary ratings)
  {
    this.version = version;
    this.service = service;
    this.options = options;
    this.ratings = ratings;
  }

  public Object clone()
  {
    try {
      return new PICSLabel((Symbol)version.clone(),
			   new URL(service.toString()),
			   (Dictionary)((Hashtable)options).clone(),
			   (Dictionary)((Hashtable)ratings).clone());
    } catch (Exception e) {
      return null;
    }
  }

  public Symbol getVersion()
  {
    return version;
  }

  public URL getService()
  {
    return service;
  }

  public Object getOption(Symbol name)
  {
    return options.get(name);
  }

  public Object getOption(String name)
  {
    return options.get(name);
  }

  // YC!!! addition
  public Object removeOption(Object name)
  {
    return options.remove(name);
  }


  protected Object setOption(Symbol name, Object option)
  {
    return options.put(name, option);
  }

  // the object option must be a UserOptionValue
  public Object setOption(String name, Object option)
  {
    return options.put(name, option);
  }

  public Dictionary getRatings()
  {
    return ratings;
  }

  public Dictionary getOptions()
  {
    return options;
  }

  public RatingValue getRating(String transmitName)
  {
    return (RatingValue)ratings.get(transmitName);
  }

  public RatingValue setRating(String transmitName,
                                         RatingValue rating)
  {
    ratings.put(transmitName, rating);
    return rating;
  }


  public void setRatings(Dictionary ratings)
  {
    this.ratings = ratings;
  }

  // YC: addition for exclude in DSig-1.0
  public Object removeRating(Object transmitName)
  {
    return ratings.remove(transmitName);
  }

  public void addRatings(Vector data)
    throws PICSParserException
  {
    for (int i = 0; i < data.size(); i += 2) {
      Object values = data.elementAt(i + 1);
      RatingValue rating;
      if (values instanceof Number)      // single number
        rating = new RatingValue(((Number)values).doubleValue());
      else if (values instanceof Vector) // list of numbers
        rating = new RatingValue((Vector)values);
      else                               // none of the above
        throw new PICSParserException("Ill-structured ratings");
      setRating(((Symbol)data.elementAt(i)).toString(), rating);
    }
  }
  

  public String toString()
  {
    Vector label = new Vector();
    label.addElement(version);
    label.addElement(service);
    label.addElement(PICS.LABELS);

    Vector nonExts = new Vector();
    nonExts.addElement(PICS.EXTENSION);
    Vector exts = new Vector();
    for (Enumeration e = this.options.keys(); e.hasMoreElements() ;) {
      Object optname = e.nextElement();
      if (optname instanceof String) 
	exts.addElement(optname);
      else
	nonExts.addElement(optname);
    }
    
    Vector sortedExts = Sorter.sortObjectEnumeration(exts.elements());
    Vector sortedNonExts = Sorter.sortObjectEnumeration(nonExts.elements());

    for (int i=0; i<sortedNonExts.size(); i++) {
      Symbol optname = (Symbol) sortedNonExts.elementAt(i);
      if (optname.equals(PICS.EXTENSION))
	for (int j=0; j<sortedExts.size(); j++) {
	  label.addElement(PICS.EXTENSION);
	  label.addElement(this.options.get(sortedExts.elementAt(j)));
	}
      else {
	label.addElement(optname);
	label.addElement(this.options.get(optname));
      }
    }
    label.addElement(PICS.RATINGS);
    Vector rats = new Vector();
    label.addElement(rats);
    Vector ratings = Sorter.sortObjectEnumeration(this.ratings.keys());
    for (int i=0; i<ratings.size(); i++) {
      Object transmit_name = ratings.elementAt(i);
      Object ratval = this.ratings.get(transmit_name);
      rats.addElement(Symbol.makeSymbol((String)transmit_name, null));
      rats.addElement(ratval);
    }
    return PICSStream.toString(label);
  }



  public void printExpr(PrintStream out)
  {
    out.print(toString());
  }
}
