package se.chalmers.cs.gf.dot;
import se.chalmers.cs.gf.dot.Absyn.*;

public class PrettyPrinter
{
  //For certain applications increasing the initial size of the buffer may improve performance.
  private static final int INITIAL_BUFFER_SIZE = 128;
  //You may wish to change the parentheses used in precedence.
  private static final String _L_PAREN = new String("(");
  private static final String _R_PAREN = new String(")");
  //You may wish to change render
  private static void render(String s)
  {
    if (s.equals("{"))
    {
       buf_.append("\n");
       indent();
       buf_.append(s);
       _n_ = _n_ + 2;
       buf_.append("\n");
       indent();
    }
    else if (s.equals("(") || s.equals("["))
       buf_.append(s);
    else if (s.equals(")") || s.equals("]"))
    {
       backup();
       buf_.append(s);
       buf_.append(" ");
    }
    else if (s.equals("}"))
    {
       _n_ = _n_ - 2;
       backup();
       backup();
       buf_.append(s);
       buf_.append("\n");
       indent();
    }
    else if (s.equals(","))
    {
       backup();
       buf_.append(s);
       buf_.append(" ");
    }
    else if (s.equals(";"))
    {
       backup();
       buf_.append(s);
       buf_.append("\n");
       indent();
    }
    else if (s.equals("")) return;
    else
    {
       buf_.append(s);
       buf_.append(" ");
    }
  }


  //  print and show methods are defined for each category.
  public static String print(se.chalmers.cs.gf.dot.Absyn.Graph foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.Graph foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String print(se.chalmers.cs.gf.dot.Absyn.GraphType foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.GraphType foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String print(se.chalmers.cs.gf.dot.Absyn.ListStmt foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.ListStmt foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String print(se.chalmers.cs.gf.dot.Absyn.Stmt foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.Stmt foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String print(se.chalmers.cs.gf.dot.Absyn.MaybeAttrList foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.MaybeAttrList foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String print(se.chalmers.cs.gf.dot.Absyn.ListAttr foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.ListAttr foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String print(se.chalmers.cs.gf.dot.Absyn.Attr foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.Attr foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String print(se.chalmers.cs.gf.dot.Absyn.ID foo)
  {
    pp(foo, 0);
    trim();
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  public static String show(se.chalmers.cs.gf.dot.Absyn.ID foo)
  {
    sh(foo);
    String temp = buf_.toString();
    buf_.delete(0,buf_.length());
    return temp;
  }
  /***   You shouldn't need to change anything beyond this point.   ***/

  private static void pp(se.chalmers.cs.gf.dot.Absyn.Graph foo, int _i_)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.Graph)
    {
       se.chalmers.cs.gf.dot.Absyn.Graph _graph = (se.chalmers.cs.gf.dot.Absyn.Graph) foo;
       if (_i_ > 0) render(_L_PAREN);
       pp(_graph.graphtype_, 0);
       render("{");
       pp(_graph.liststmt_, 0);
       render("}");
       if (_i_ > 0) render(_R_PAREN);
    }
  }

  private static void pp(se.chalmers.cs.gf.dot.Absyn.GraphType foo, int _i_)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.Digraph)
    {
       se.chalmers.cs.gf.dot.Absyn.Digraph _digraph = (se.chalmers.cs.gf.dot.Absyn.Digraph) foo;
       if (_i_ > 0) render(_L_PAREN);
       render("digraph");
       if (_i_ > 0) render(_R_PAREN);
    }
  }

  private static void pp(se.chalmers.cs.gf.dot.Absyn.ListStmt foo, int _i_)
  {
     for (java.util.Iterator<Stmt> it = foo.iterator(); it.hasNext();)
     {
       pp(it.next(), 0);
       if (it.hasNext()) {
         render(";");
       } else {
         render(";");
       }
     }
  }

  private static void pp(se.chalmers.cs.gf.dot.Absyn.Stmt foo, int _i_)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.NodeStmt)
    {
       se.chalmers.cs.gf.dot.Absyn.NodeStmt _nodestmt = (se.chalmers.cs.gf.dot.Absyn.NodeStmt) foo;
       if (_i_ > 0) render(_L_PAREN);
       pp(_nodestmt.id_, 0);
       pp(_nodestmt.maybeattrlist_, 0);
       if (_i_ > 0) render(_R_PAREN);
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.EdgeStmt)
    {
       se.chalmers.cs.gf.dot.Absyn.EdgeStmt _edgestmt = (se.chalmers.cs.gf.dot.Absyn.EdgeStmt) foo;
       if (_i_ > 0) render(_L_PAREN);
       pp(_edgestmt.id_1, 0);
       render("->");
       pp(_edgestmt.id_2, 0);
       pp(_edgestmt.maybeattrlist_, 0);
       if (_i_ > 0) render(_R_PAREN);
    }
  }

  private static void pp(se.chalmers.cs.gf.dot.Absyn.MaybeAttrList foo, int _i_)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.NoAttrList)
    {
       se.chalmers.cs.gf.dot.Absyn.NoAttrList _noattrlist = (se.chalmers.cs.gf.dot.Absyn.NoAttrList) foo;
       if (_i_ > 0) render(_L_PAREN);
       if (_i_ > 0) render(_R_PAREN);
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.AnAttrList)
    {
       se.chalmers.cs.gf.dot.Absyn.AnAttrList _anattrlist = (se.chalmers.cs.gf.dot.Absyn.AnAttrList) foo;
       if (_i_ > 0) render(_L_PAREN);
       render("[");
       pp(_anattrlist.listattr_, 0);
       render("]");
       if (_i_ > 0) render(_R_PAREN);
    }
  }

  private static void pp(se.chalmers.cs.gf.dot.Absyn.ListAttr foo, int _i_)
  {
     for (java.util.Iterator<Attr> it = foo.iterator(); it.hasNext();)
     {
       pp(it.next(), 0);
       if (it.hasNext()) {
         render(",");
       } else {
         render("");
       }
     }
  }

  private static void pp(se.chalmers.cs.gf.dot.Absyn.Attr foo, int _i_)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.Attr)
    {
       se.chalmers.cs.gf.dot.Absyn.Attr _attr = (se.chalmers.cs.gf.dot.Absyn.Attr) foo;
       if (_i_ > 0) render(_L_PAREN);
       pp(_attr.id_1, 0);
       render("=");
       pp(_attr.id_2, 0);
       if (_i_ > 0) render(_R_PAREN);
    }
  }

  private static void pp(se.chalmers.cs.gf.dot.Absyn.ID foo, int _i_)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.IdentID)
    {
       se.chalmers.cs.gf.dot.Absyn.IdentID _identid = (se.chalmers.cs.gf.dot.Absyn.IdentID) foo;
       if (_i_ > 0) render(_L_PAREN);
       pp(_identid.ident_, 0);
       if (_i_ > 0) render(_R_PAREN);
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.StringID)
    {
       se.chalmers.cs.gf.dot.Absyn.StringID _stringid = (se.chalmers.cs.gf.dot.Absyn.StringID) foo;
       if (_i_ > 0) render(_L_PAREN);
       printQuoted(_stringid.string_);
       if (_i_ > 0) render(_R_PAREN);
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.IntID)
    {
       se.chalmers.cs.gf.dot.Absyn.IntID _intid = (se.chalmers.cs.gf.dot.Absyn.IntID) foo;
       if (_i_ > 0) render(_L_PAREN);
       pp(_intid.integer_, 0);
       if (_i_ > 0) render(_R_PAREN);
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.DoubleID)
    {
       se.chalmers.cs.gf.dot.Absyn.DoubleID _doubleid = (se.chalmers.cs.gf.dot.Absyn.DoubleID) foo;
       if (_i_ > 0) render(_L_PAREN);
       pp(_doubleid.double_, 0);
       if (_i_ > 0) render(_R_PAREN);
    }
  }


  private static void sh(se.chalmers.cs.gf.dot.Absyn.Graph foo)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.Graph)
    {
       se.chalmers.cs.gf.dot.Absyn.Graph _graph = (se.chalmers.cs.gf.dot.Absyn.Graph) foo;
       render("(");
       render("Graph");
       sh(_graph.graphtype_);
       render("[");
       sh(_graph.liststmt_);
       render("]");
       render(")");
    }
  }

  private static void sh(se.chalmers.cs.gf.dot.Absyn.GraphType foo)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.Digraph)
    {
       se.chalmers.cs.gf.dot.Absyn.Digraph _digraph = (se.chalmers.cs.gf.dot.Absyn.Digraph) foo;
       render("Digraph");
    }
  }

  private static void sh(se.chalmers.cs.gf.dot.Absyn.ListStmt foo)
  {
     for (java.util.Iterator<Stmt> it = foo.iterator(); it.hasNext();)
     {
       sh(it.next());
       if (it.hasNext())
         render(",");
     }
  }

  private static void sh(se.chalmers.cs.gf.dot.Absyn.Stmt foo)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.NodeStmt)
    {
       se.chalmers.cs.gf.dot.Absyn.NodeStmt _nodestmt = (se.chalmers.cs.gf.dot.Absyn.NodeStmt) foo;
       render("(");
       render("NodeStmt");
       sh(_nodestmt.id_);
       sh(_nodestmt.maybeattrlist_);
       render(")");
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.EdgeStmt)
    {
       se.chalmers.cs.gf.dot.Absyn.EdgeStmt _edgestmt = (se.chalmers.cs.gf.dot.Absyn.EdgeStmt) foo;
       render("(");
       render("EdgeStmt");
       sh(_edgestmt.id_1);
       sh(_edgestmt.id_2);
       sh(_edgestmt.maybeattrlist_);
       render(")");
    }
  }

  private static void sh(se.chalmers.cs.gf.dot.Absyn.MaybeAttrList foo)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.NoAttrList)
    {
       se.chalmers.cs.gf.dot.Absyn.NoAttrList _noattrlist = (se.chalmers.cs.gf.dot.Absyn.NoAttrList) foo;
       render("NoAttrList");
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.AnAttrList)
    {
       se.chalmers.cs.gf.dot.Absyn.AnAttrList _anattrlist = (se.chalmers.cs.gf.dot.Absyn.AnAttrList) foo;
       render("(");
       render("AnAttrList");
       render("[");
       sh(_anattrlist.listattr_);
       render("]");
       render(")");
    }
  }

  private static void sh(se.chalmers.cs.gf.dot.Absyn.ListAttr foo)
  {
     for (java.util.Iterator<Attr> it = foo.iterator(); it.hasNext();)
     {
       sh(it.next());
       if (it.hasNext())
         render(",");
     }
  }

  private static void sh(se.chalmers.cs.gf.dot.Absyn.Attr foo)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.Attr)
    {
       se.chalmers.cs.gf.dot.Absyn.Attr _attr = (se.chalmers.cs.gf.dot.Absyn.Attr) foo;
       render("(");
       render("Attr");
       sh(_attr.id_1);
       sh(_attr.id_2);
       render(")");
    }
  }

  private static void sh(se.chalmers.cs.gf.dot.Absyn.ID foo)
  {
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.IdentID)
    {
       se.chalmers.cs.gf.dot.Absyn.IdentID _identid = (se.chalmers.cs.gf.dot.Absyn.IdentID) foo;
       render("(");
       render("IdentID");
       sh(_identid.ident_);
       render(")");
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.StringID)
    {
       se.chalmers.cs.gf.dot.Absyn.StringID _stringid = (se.chalmers.cs.gf.dot.Absyn.StringID) foo;
       render("(");
       render("StringID");
       sh(_stringid.string_);
       render(")");
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.IntID)
    {
       se.chalmers.cs.gf.dot.Absyn.IntID _intid = (se.chalmers.cs.gf.dot.Absyn.IntID) foo;
       render("(");
       render("IntID");
       sh(_intid.integer_);
       render(")");
    }
    if (foo instanceof se.chalmers.cs.gf.dot.Absyn.DoubleID)
    {
       se.chalmers.cs.gf.dot.Absyn.DoubleID _doubleid = (se.chalmers.cs.gf.dot.Absyn.DoubleID) foo;
       render("(");
       render("DoubleID");
       sh(_doubleid.double_);
       render(")");
    }
  }


  private static void pp(Integer n, int _i_) { buf_.append(n); buf_.append(" "); }
  private static void pp(Double d, int _i_) { buf_.append(d); buf_.append(" "); }
  private static void pp(String s, int _i_) { buf_.append(s); buf_.append(" "); }
  private static void pp(Character c, int _i_) { buf_.append("'" + c.toString() + "'"); buf_.append(" "); }
  private static void sh(Integer n) { render(n.toString()); }
  private static void sh(Double d) { render(d.toString()); }
  private static void sh(Character c) { render(c.toString()); }
  private static void sh(String s) { printQuoted(s); }
  private static void printQuoted(String s) { render("\"" + s + "\""); }
  private static void indent()
  {
    int n = _n_;
    while (n > 0)
    {
      buf_.append(" ");
      n--;
    }
  }
  private static void backup()
  {
   String s = buf_.toString();

     if (s.substring(buf_.length() - 1, buf_.length()).equals(" ")) {
       buf_.setCharAt(buf_.length() - 1, '\"');
       buf_.setLength(buf_.length() - 1);
     }
  }
  private static void trim()
  {
     while (buf_.length() > 0 && buf_.charAt(0) == ' ')
        buf_.deleteCharAt(0); 
    while (buf_.length() > 0 && buf_.charAt(buf_.length()-1) == ' ')
        buf_.deleteCharAt(buf_.length()-1);
  }
  private static int _n_ = 0;
  private static StringBuilder buf_ = new StringBuilder(INITIAL_BUFFER_SIZE);
}