package util.statemachine;

import java.util.Set;

import util.gdl.grammar.Gdl;
import util.gdl.grammar.GdlConstant;
import util.gdl.grammar.GdlFunction;
import util.gdl.grammar.GdlRelation;
import util.gdl.grammar.GdlSentence;

public abstract class MachineState {
    /* Abstract methods */
    
    /**
     * getContents returns the GDL sentences which determine the current state
     * of the game being played. Two given states with identical GDL sentences
     * should be identical states of the game.
     */
	public abstract Set<GdlSentence> getContents();

	/* Utility methods */
    public int hashCode()
    {
        return getContents().hashCode();
    }

    public String toString()
    {
    	Set<GdlSentence> contents = getContents();
    	if(contents == null)
    		return "(MachineState with null contents)";
    	else
    		return contents.toString();
    }	

    public boolean equals(Object o)
    {
        if ((o != null) && (o instanceof MachineState))
        {
            MachineState state = (MachineState) o;
            return state.getContents().equals(getContents());
        }

        return false;
    }    
    
    public final String toXML()
    {
        String rval = "<match>\n\n<herstory>\n\n\t<state>\n\n";
        Set<GdlSentence> theContents = getContents();
        for(GdlSentence sentence : theContents)
        {
            rval += gdlToXML(sentence);
        }
        rval += "\n\t</state>\n\n</herstory>\n\n</match>\n";
        return rval;
    }
    
    private final String gdlToXML(Gdl gdl)
    {
        String rval = "";
        if(gdl instanceof GdlConstant)
        {
            GdlConstant c = (GdlConstant)gdl;
            return c.getValue();
        } else if(gdl instanceof GdlFunction) {
            GdlFunction f = (GdlFunction)gdl;
            if(f.getName().toString().equals("true"))
            {
                return "<fact>\n\n"+gdlToXML(f.get(0))+"</fact>\n\n";
            }
            else
            {
                rval += "\t<relation>"+f.getName()+"</relation>\n\n";
                for(int i=0; i<f.arity(); i++)
                    rval += "\t\t<argument>"+gdlToXML(f.get(i))+"</argument>\n\n";
                return rval;
            }
        } else if (gdl instanceof GdlRelation) {
            GdlRelation relation = (GdlRelation) gdl;
            if(relation.getName().toString().equals("true"))
            {
                for(int i=0; i<relation.arity(); i++)
                    rval+="<fact>\n\n"+gdlToXML(relation.get(i))+"</fact>\n\n";
                return rval;
            } else {
                rval+="\t<relation>"+relation.getName()+"</relation>\n\n";
                for(int i=0; i<relation.arity(); i++)
                    rval+="\t\t<argument>"+gdlToXML(relation.get(i))+"</argument>\n\n";
                return rval;
            }
        } else {
            System.err.println("Oh oh: "+gdl.toString());
            return "";
        }
    }
}
@@ -1259,43 +1259,16 @@
 = %22%3C
-match%3E%5Cn%5Cn%3Cherstory%3E%5Cn%5Cn%5Ct%3C
 state%3E%5Cn
 %5Cn%22;
@@ -1263,18 +1263,16 @@
 state%3E%5Cn
-%5Cn
 %22;%0D%0A    
@@ -1455,20 +1455,16 @@
 += %22
-%5Cn%5Ct
 %3C/state%3E
 %5Cn%5Cn
@@ -1463,25 +1463,241 @@
 ate%3E
-%5Cn%5Cn%3C/herstory%3E%5Cn
+%22;%0D%0A        return rval;%0D%0A    %7D%0D%0A    %0D%0A    // TODO: Do we really need this method?%0D%0A    public final String toMatchXML()%0D%0A    %7B%0D%0A        String rval = %22%3Cmatch%3E%5Cn %3Cherstory%3E%5Cn%22;%0D%0A        rval += toXML();%0D%0A        rval += %22 %3C/herstory%3E
 %5Cn%3C/
@@ -1702,18 +1702,16 @@
 %3C/match%3E
-%5Cn
 %22;%0D%0A    
@@ -2141,24 +2141,26 @@
 return %22
+%5Ct
 %3Cfact%3E%5Cn
 %5Cn%22+gdlT
@@ -2143,34 +2143,32 @@
 turn %22%5Ct%3Cfact%3E%5Cn
-%5Cn
 %22+gdlToXML(f.get
@@ -2169,24 +2169,26 @@
 (f.get(0))+%22
+%5Ct
 %3C/fact%3E%5Cn%5Cn%22
@@ -2176,34 +2176,32 @@
 0))+%22%5Ct%3C/fact%3E%5Cn
-%5Cn
 %22;%0D%0A            
@@ -2263,16 +2263,18 @@
 l += %22%5Ct
+%5Ct
 %3Crelatio
@@ -2295,34 +2295,32 @@
 )+%22%3C/relation%3E%5Cn
-%5Cn
 %22;%0D%0A            
@@ -2425,34 +2425,32 @@
 )+%22%3C/argument%3E%5Cn
-%5Cn
 %22;%0D%0A            
@@ -2746,24 +2746,26 @@
  rval+=%22
+%5Ct
 %3Cfact%3E%5Cn
 %5Cn%22+gdlT
@@ -2756,18 +2756,16 @@
 %3Cfact%3E%5Cn
-%5Cn
 %22+gdlToX
@@ -2785,16 +2785,18 @@
 et(i))+%22
+%5Ct
 %3C/fact%3E%5C
@@ -2792,26 +2792,24 @@
 %22%5Ct%3C/fact%3E%5Cn
-%5Cn
 %22;%0D%0A        
@@ -2877,16 +2877,18 @@
 val+=%22%5Ct
+%5Ct
 %3Crelatio
@@ -2924,18 +2924,16 @@
 ation%3E%5Cn
-%5Cn
 %22;%0D%0A    
@@ -3066,18 +3066,16 @@
 ument%3E%5Cn
-%5Cn
 %22;%0D%0A    
@@ -3169,14 +3169,53 @@
 ln(%22
-Oh oh:
+MachineState gdlToXML Error: could not handle
  %22+g

Split out the generation of XML for an individual state from the generation of XML for a state wrapped in an otherwise-empty match.