import java.applet.*;
import java.awt.*;
import java.util.*;
import java.awt.event.*;

public class GSPlanner extends Applet implements ActionListener{

String[][][] operators={
    {{"fry_eggs"},
    {"have_eggs","have_pan"},
    {"pan_is_clean","have_eggs"},
    {"have_ommelette"}},
    
    {{"clean_pan"},
    {"have_water","have_pan"},
    {},
    {"pan_is_clean"}},
    
    };

String[] initialState={"have_eggs","have_pan","have_water"};
String[] goalState={"pan_is_clean","have_ommelette"};

Vector goalStack=new Vector();
Vector currentPlan=new Vector();
Vector currentState=new Vector();
TextField currentStateT=new TextField("",62);
List currentPlanL=new List(10);
//    {public Dimension getPreferredSize(){return getPreferredSize(20);}};
List goalStackL=new List(10);
Label message=new Label("");
public void init(){
    Button b;
    Panel p,p2;
    setLayout(new BorderLayout());
    p=new Panel();
    p.setLayout(new BorderLayout());
    p.add("North",new Label("Current Plan:              "));
    p.add("South",currentPlanL);
    add("West",p);
    p=new Panel();
    p.setLayout(new BorderLayout());
    p.add("North",new Label(
        "Goal Stack:                                                                                                                  "));
    p.add("South",goalStackL);
    add("East",p);
    p=new Panel();
    p.setLayout(new BorderLayout());
    p2=new Panel();
    p2.setLayout(new BorderLayout());
    p2.add("West",new Label("Current State:"));
    p2.add("East",currentStateT);
    p.add("North",p2);
    p.add("East",b=new Button("Reset"));
    b.addActionListener(new ActionListener(){
        public void actionPerformed(ActionEvent ae){reset();}
    });
    p.add("West",b=new Button("Step"));
    p.add("Center",message);
    b.addActionListener(this);
    add("South",p);
    
    reset();
}

public void reset(){
    Vector t=new Vector();
    goalStack.removeAllElements();
    for(int i=0;i<goalState.length;i++) t.addElement(goalState[i]);
    goalStack.addElement(t);
    currentState.removeAllElements();
    for(int i=0;i<initialState.length;i++) currentState.addElement(initialState[i]);
    currentPlan.removeAllElements();
    refresh();
}

void refresh(){
    String t=new String("");
    for(int i=0;i<currentState.size();i++) t=t+(String)currentState.elementAt(i)+" ";
    currentStateT.setText(t);
    currentPlanL.removeAll();
    for(int i=0;i<currentPlan.size();i++)
        currentPlanL.add((String)currentPlan.elementAt(i));
    goalStackL.removeAll();
    for(int i=0;i<10;i++)
        if(10-i>goalStack.size()) goalStackL.add("");
        else goalStackL.add(conjunction((Vector)goalStack.elementAt(9-i)));    
}

String conjunction(Vector v){
    String t=new String("");
    for(int i=0;i<v.size();i++){
        t=t+(String)v.elementAt(i)+" ";
    }
    return t;
}
String conjunction(String[] a){
    String t=new String("");
    for(int i=0;i<a.length;i++){
        t=t+a[i]+" ";
    }
    return t;
}

public void actionPerformed(ActionEvent ae){
    if(goalStack.size()==0) return;
    Vector t=(Vector)goalStack.lastElement();
    goalStack.removeElementAt(goalStack.size()-1);
    refresh();
    if(t.size()>1){ //conjunction of goals
        message("Found conjunction of goals ( "+conjunction(t)+").",2000);
        message("Ignoring goals already in Current State ...",2000);
        for(int i=t.size();i-->0;){
            if(stringInVector((String)t.elementAt(i),currentState))
                t.removeElementAt(i);
        }
        if(t.size()>1){
            message("... pushing resulting conjuntion ( "+conjunction(t)
                +") onto Goal Stack ...",2000);
            goalStack.addElement(t); //push a vector with the conjunction
            refresh();
            message("... done.",2000);        
        }
        if(t.size()>0){
            message("... pushing individual goals ( "+conjunction(t)
                +") onto Goal Stack ...",2000);
            for(int i=t.size();i-->0;){
                Vector push=new Vector();
                push.addElement((String)t.elementAt(i));
                goalStack.addElement(push); //push a vector of only one element
            }
            refresh();
            message("... done.",2000);        
        }
        if(t.size()==0){
            message("... all goals where already in Current State.",2000);
        }
        return;
    }
    //only one in top, may be a goal or an operator
    String top=(String)t.elementAt(0);
    for(int i=0;i<operators.length;i++){
        if(stringInArray(top,operators[i][3])){
            message("Found goal ("+top+").",2000);
            //push operator onto goals stack
            message("Pushing it's operator ("
                +operators[i][0][0]+") onto Goal Stack ...",2000);
            Vector push=new Vector(),p2=new Vector();
            push.addElement(operators[i][0][0]);
            goalStack.addElement(push);
            refresh();
            message("... done.",2000);
            //push operator preconditions on to goal stack
            for(int k=0;k<operators[i][1].length;k++)
                p2.addElement(operators[i][1][k]);
            message("Pushing operator's preconditions ( "+
                conjunction(p2)+") onto Goal Stack ...",2000);
            goalStack.addElement(p2);
            refresh();
            message("... done.",2000);
            return;
        }
    }
    //top must be an operator
    for(int i=0;i<operators.length;i++){
        if(top.equals(operators[i][0][0])){
            message("Found operator ("+top+").",2000);
            //push top onto the current plan
            message("Adding operator to Current Plan ...",2000);
            currentPlan.addElement(top);
            refresh();
            message("... done.",2000);
            //apply tops add and delete lists to the current state
            message("Applying operator's delete list ( "+conjunction(operators[i][2])+
                ")...",2000);
            for(int j=currentState.size();j-->0;)
                if(stringInArray((String)currentState.elementAt(j),operators[i][2]))
                    currentState.removeElementAt(j);
            refresh();
            message("... done.",2000);
            message("Applying operator's add list ( "+conjunction(operators[i][3])
                +")...",2000);
            for(int j=operators[i][3].length;j-->0;)
                currentState.addElement(operators[i][3][j]);
            refresh();
            message("... done.",2000);
            return;
        }        
    }
    message("Unknown element ("+top+") on top of stack.",2000);
    goalStack.addElement(t);//just put it as it was
    refresh();
    //flow should never reach here

}
void message(String m, long w){
    message.setText("  "+m);
    try{synchronized(this){wait(w*2);}}catch(InterruptedException e){}
    message.setText("");
}

boolean stringInVector(String s, Vector v){
    for(int i=0;i<v.size();i++)
        if(((String)v.elementAt(i)).equals(s)) return true;
    return false;
}
boolean stringInArray(String s, String[] a){
    for(int i=0;i<a.length;i++)
        if(a[i].equals(s)) return true;
    return false;
}



}