//  (c) 2010 Thomas A. Alspaugh.  All rights reserved.
package oo;


/**
  An orientation of a mattress. &nbsp;
  There are four possible orientations
  ({@link #HLT},
   {@link #HRB},
   {@link #FLB}, and
   {@link #FRT});&nbsp;
  no others can be constructed.&nbsp;

  <p>
  This class ensures that the only orientations are
  the four physically-possible orientations.&nbsp;
  Each orientation is embodied by
  a singleton object of a subclass of Orientation.

*/
public abstract class Orientation implements PRYable {

  /**
    The singleton HLT orientation.
  */
  static public final Orientation HLT = OrientationHLT.singleton;

  /**
    The singleton HRB orientation.
  */
  static public final Orientation HRB = OrientationHRB.singleton;

  /**
    The singleton FLB orientation.
  */
  static public final Orientation FLB = OrientationFLB.singleton;

  /**
    The singleton FRT orientation.
  */
  static public final Orientation FRT = OrientationFRT.singleton;

  // ---------------------------------------------------------------

  /**
    "HLT", "HRB", "FLB", or "FRT",
    whichever describes this orientation.
  */
  private final String toString;

  /**
    Hidden default constructor, always throws an exception.
  */
  @SuppressWarnings("unused")
  private Orientation() {
    throw new RuntimeException("Default constructor not to be called");
  }

  /**
    Protected constructor for orientations.
    @param _toString  "HLT", "HRB", "FLB", or "FRT".
  */
  protected Orientation(String _toString) {
    if /**/ (_toString.equals("HLT")) {  /* do nothing */  }
    else if (_toString.equals("HRB")) {  /* do nothing */  }
    else if (_toString.equals("FLB")) {  /* do nothing */  }
    else if (_toString.equals("FRT")) {  /* do nothing */  }
    else {
      throw new RuntimeException("_toString \"" + _toString + "\"");
    }
    toString = _toString;
  }

  /**
    "HLT", "HRB", "FLB", or "FRT",
    whichever describes this orientation.
  */
  public String toString() {  return toString;  }

  public boolean headRed()  {  return 'H' == toString.charAt(0);  }
  public boolean leftBlue() {  return 'L' == toString.charAt(1);  }
  public boolean topGreen() {  return 'T' == toString.charAt(2);  }

  abstract public Orientation roll();
  abstract public Orientation pitch();
  abstract public Orientation yaw();

  /**
    The HLT orientation (head, left, top).
  */
  public Orientation HLT() {  return OrientationHLT.singleton;  }

  /**
    The HRB orientation (head, right, bottom).
  */
  public Orientation HRB() {  return OrientationHRB.singleton;  }

  /**
    The FLB orientation (foot, left, bottom).
  */
  public Orientation FLB() {  return OrientationFLB.singleton;  }

  /**
    The FRT orientation (foot, right, top).
  */
  public Orientation FRT() {  return OrientationFRT.singleton;  }

}

/**
  Singleton class for the HLT orientation.
*/
class OrientationHLT extends Orientation {
  /**  Singleton object of this class.  */
  static final OrientationHLT singleton = new OrientationHLT();
  /**  Private constructor for HLT.  */
  private OrientationHLT() {
    super(  "HLT");
  }
  public Orientation roll()  {  return HRB();  }
  public Orientation pitch() {  return FLB();  }
  public Orientation yaw()   {  return FRT();  }
}

/**
  Singleton class for the HRB orientation.
*/
class OrientationHRB extends Orientation {
  /**  Singleton object of this class.  */
  static final OrientationHRB singleton = new OrientationHRB();
  /**  Private constructor for HRB.  */
  private OrientationHRB() {
    super(  "HRB");
  }
  public Orientation roll()  {  return HLT();  }
  public Orientation pitch() {  return FRT();  }
  public Orientation yaw()   {  return FLB();  }
}

/**
  Singleton class for the FLB orientation.
*/
class OrientationFLB extends Orientation {
  /**  Singleton object of this class.  */
  static final OrientationFLB singleton = new OrientationFLB();
  /**  Private constructor for FLB.  */
  private OrientationFLB() {
    super(  "FLB");
  }
  public Orientation roll()  {  return FRT();  }
  public Orientation pitch() {  return HLT();  }
  public Orientation yaw()   {  return HRB();  }
}

/**
  Singleton class for the FRT orientation.
*/
class OrientationFRT extends Orientation {
  /**  Singleton object of this class.  */
  static final OrientationFRT singleton = new OrientationFRT();
  /**  Private constructor for FRT.  */
  private OrientationFRT() {
    super(  "FRT");
  }
  public Orientation roll()  {  return FLB();  }
  public Orientation pitch() {  return HRB();  }
  public Orientation yaw()   {  return HLT();  }
}
