package utils;

public class Pair implements Comparable {
  Object cardata;
  Object cdrdata;

  public Pair(Object car, Object cdr) {
    cardata = car;
    cdrdata = cdr;
  }

  public Object car() {
    return cardata;
  }

  public Object cdr() {
    return cdrdata;
  }

  public String toString() {
    String carstr,cdrstr;
    if(cardata != null) carstr = cardata.toString(); else carstr = "#f";
    if(cdrdata != null) cdrstr = cdrdata.toString(); else cdrstr = "#f";
    return "("+carstr+" . "+cdrstr+")";
  }

  public boolean equals(Object p) {
    if(!(p instanceof Pair)) return false;
    Pair pp = (Pair)p;
    if(!((cardata==null && pp.cardata==null) ||
         (cardata!=null && cardata.equals(pp.cardata)))) return false;
    if(!((cdrdata==null && pp.cdrdata==null) ||
         (cdrdata!=null && cdrdata.equals(pp.cdrdata)))) return false;
    return true;
  }

  public int compareTo(Object o) {
    if(!(o instanceof Pair)) throw new ClassCastException();
    // are the car elements comparable?
    int v=0;
    if(this.cardata==null && ((Pair)o).cardata!=null) return -1;
    if(this.cardata!=null && ((Pair)o).cardata==null) return 1;
    if(this.cardata!=null) {
      if(!(this.cardata instanceof Comparable)) throw new ClassCastException();
      v = ((Comparable)this.cardata).compareTo(((Pair)o).cardata);
      if(v!=0) return v;
    }
    if(this.cdrdata==null && ((Pair)o).cdrdata!=null) return -1;
    if(this.cdrdata!=null && ((Pair)o).cdrdata==null) return 1;
    if(this.cdrdata!=null) {
      if(!(this.cdrdata instanceof Comparable)) throw new ClassCastException();
      v = ((Comparable)this.cdrdata).compareTo(((Pair)o).cdrdata);
    }
    return v;
  }

  public int hashCode() {
    int v=0;
    if(cardata!=null) v+=cardata.hashCode();
    if(cdrdata!=null) v+=cdrdata.hashCode();
    return v;
  }

  public Object clone() {
    return new Pair(cardata,cdrdata);
  }
}
