/*  RuleApplet 

        Micro Projet ARTC 1997/1998
	(C) 1998 DPSV Team Touts Droits Réservés
        Marc-Aurèle DARCHE
        Emmanuel PIERRE
        Marc-Olivier VARROY
        Antoine SOULIEZ

*/

import java.awt.*;
import java.applet.*;
import java.util.* ;
import java.io.StreamTokenizer;
import java.io.InputStream;
import java.io.BufferedInputStream;
import java.net.URL;
import java.net.MalformedURLException;


public class RuleApplet extends Applet {


    // l'utilisateur a séléctionné une variable
    void choice2_Clicked(Event event) {
       String varName = choice2.getSelectedItem() ;
       choice3.removeAll() ;

       RuleVariable rvar = (RuleVariable)currentRuleBase.variableList.get(varName);
       Enumeration labels = rvar.labels.elements();
       while (labels.hasMoreElements()) {
          choice3.addItem(((String)labels.nextElement())) ;
       }
	}

    //  l'utilisateur a choisi une valeur pour une variable
	void choice3_Clicked(Event event) {
       String varName = choice2.getSelectedItem() ;
       String varValue = choice3.getSelectedItem() ;

       RuleVariable rvar = (RuleVariable)currentRuleBase.variableList.get(varName);
       rvar.setValue(varValue) ;
       textArea3.appendText("\n" + rvar.name + " set to " + varValue) ;

	}

    	//  l'utilisateur a activé le bouton variableFind 
   	// on fait un cycle d'inférence
	void button1_Clicked(Event event) {
	        String goal = textField1.getText() ;

	        textArea2.appendText("\n --- Demarrage du cycle d'inference --- \n");
	        currentRuleBase.displayVariables(textArea2) ;

	        if (radioButton1.getState() == true) currentRuleBase.forwardChain();
	   	if (radioButton2.getState() == true) currentRuleBase.backwardChain(goal);
	        currentRuleBase.displayVariables(textArea2) ;
	        textArea2.appendText("\n --- Fin du cycle d'inference --- \n");
	}

    void button3_Clicked(Event event) {

		//{{CONNECTION
		// Clear the text for TextArea
		textArea1.setText("");
		textArea2.setText("");
		textArea3.setText("");
		//}}

        currentRuleBase.reset() ;
        currentRuleBase.displayRules(textArea1);
        currentRuleBase.displayVariables(textArea3) ;
	}

// affiche une fenêtre pour obtenir de l'Expert la valeur pour une variable
static public String waitForAnswer(String prompt, String labels) {

	// position dialog over parent dialog
    Point p = frame.getLocation() ;
    dlg = new RuleVarDialog(frame, true) ;
	dlg.label1.setText("   " + prompt + " (" + labels + ")");
    dlg.setLocation(400, 250) ;
    dlg.show() ;
    String ans = dlg.getText() ;
    return ans ;

}


	public void init() {
		super.init();


		//{{INIT_CONTROLS
		setLayout(null);
		addNotify();
		resize(624,527);
		button1 = new java.awt.Button("Trouve le But");
		//button1.reshape(36,468,108,30);
		button1.reshape(36,478,108,30);
		add(button1);
		button3 = new java.awt.Button("Reset");
		//button3.reshape(444,468,108,30);
		button3.reshape(444,478,108,30);
		add(button3);
		textArea1 = new java.awt.TextArea();
		textArea1.reshape(12,48,312,144);
		add(textArea1);
		textArea2 = new java.awt.TextArea();
		// textArea2.reshape(12,216,600,168);
		textArea2.reshape(12,216,600,200);
		add(textArea2);
		label2 = new java.awt.Label("Fenetre de Tracage");
		label2.reshape(24,192,168,24);
		add(label2);
		label1 = new java.awt.Label("Systeme de traitement d'une connaissance");
		label1.reshape(24,4,250,16);
		add(label1);
		label11 = new java.awt.Label("(C) 1998 DPSV Team");
		label11.reshape(28,16,170,32);
		add(label11);
		Group1 = new CheckboxGroup();
		radioButton1 = new java.awt.Checkbox("Chainage avant", Group1, false);
		// radioButton1.reshape(36,396,156,21);
		radioButton1.reshape(36,430,156,21);
		add(radioButton1);
		choice3 = new java.awt.Choice();
		add(choice3);
		choice3.reshape(480,36,135,24);
		label5 = new java.awt.Label("Valeur");
		label5.reshape(480,12,95,24);
		add(label5);
		choice2 = new java.awt.Choice();
		add(choice2);
		choice2.reshape(336,36,137,24);
		textArea3 = new java.awt.TextArea();
		textArea3.reshape(336,72,276,122);
		add(textArea3);
		label4 = new java.awt.Label("Variable");
		label4.reshape(336,12,109,24);
		add(label4);
		radioButton2 = new java.awt.Checkbox("Chainage arriere", Group1, false);
		//radioButton2.reshape(36,420,156,24);
		radioButton2.reshape(36,450,156,24);
		add(radioButton2);
		textField1 = new java.awt.TextField();
		//textField1.reshape(324,420,142,27);
		textField1.reshape(324,446,142,27);
		add(textField1);
		label3 = new java.awt.Label("But");
		//label3.reshape(324,384,80,30);
		label3.reshape(324,424,80,30);
		add(label3);
		//}}

	 	frame = new Frame("Demandes a l'Expert") ;
	 	frame.resize(50,50) ;
	 	frame.setLocation(100,100) ;

	 	base = new RuleBase("Base de regles") ;
	 	base.setDisplay(textArea2) ;
	 	initRuleBase(base) ;
        	currentRuleBase = base ;


        // initialize textAreas and list controls
        currentRuleBase.displayRules(textArea1) ;
        //currentRuleBase.displayVariables(textArea3) ;
        radioButton1.setState(true) ;
	
       Enumeration vars = currentRuleBase.variableList.elements() ;
       while (vars.hasMoreElements()) {
         choice2.addItem(((RuleVariable)vars.nextElement()).name) ;
       }
       currentRuleBase.displayVariables(textArea3) ;


}

	public boolean handleEvent(Event event) {
		if (event.target == button1 && event.id == Event.ACTION_EVENT) {
			button1_Clicked(event);
			return true;
		}if (event.target == button3 && event.id == Event.ACTION_EVENT) {
			button3_Clicked(event);
			return true;
		}
		if (event.target == dlg && event.id == Event.ACTION_EVENT) {
			return dlg.handleEvent(event);
		}
	    if (event.target == choice2 && event.id == Event.ACTION_EVENT) {
			choice2_Clicked(event);
			return true;
	    }
	        if (event.target == choice3 && event.id == Event.ACTION_EVENT) {
			choice3_Clicked(event);
			return true;
	    }
		return super.handleEvent(event);
	}

	//{{DECLARE_CONTROLS
	java.awt.Button button1;
	java.awt.Button button2;
	java.awt.Button button3;
	java.awt.TextArea textArea1;
	java.awt.TextArea textArea2;
	java.awt.Label label2;
	java.awt.Label label1;
	java.awt.Label label11;
	java.awt.Choice choice1;
	java.awt.Checkbox radioButton1;
	CheckboxGroup Group1;
	java.awt.Choice choice3;
	java.awt.Label label5;
	java.awt.Choice choice2;
	java.awt.TextArea textArea3;
	java.awt.Label label4;
	java.awt.Checkbox radioButton2;
	java.awt.TextField textField1;
	java.awt.Label label3;
	//}}

	static Frame frame ;
	static RuleVarDialog dlg ;
	static RuleBase base ;
    	static RuleBase currentRuleBase ;
//



  // Lecture de la base de règle
  public void initRuleBase(RuleBase rb) {

 	InputStream is = null;
        URL urlFactBase;

	String strParam = getParameter("DB");
	String strBaseName = (strParam == null) ? "database.db" : strParam;
	int flag=0;
	StringTokenizer Tk,Tks,Tke;
	String sTk,ssTk,esTk,nsTk;

 	rb.goalClauseStack = new Stack() ; // buts et sous-buts

  	rb.variableList = new Hashtable() ;
	rb.ruleList = new Vector() ;
	Hashtable symbols = new Hashtable(); // table des variables

	// définit les conditions
 	Condition cEquals = new Condition("=") ;
 	Condition cNotEquals = new Condition("!=") ;

        try {
		textArea2.appendText("Chargement de "+strBaseName+"\n");
		urlFactBase = new URL(this.getDocumentBase(), strBaseName);

        try {
        	is =  urlFactBase.openStream();

        	StreamTokenizer st = new StreamTokenizer(new BufferedInputStream(is, 4000));
        	//st.eolIsSignificant(true);
		// ce qui définit un token
        	st.commentChar('#');
		st.wordChars('[', ']');
		st.wordChars(':',':');
		st.wordChars(' ',' ');
		st.wordChars('?','?');
		st.wordChars('\'','\'');
		st.wordChars('=','=');

	 scan:
        	while (true) {
		switch (st.nextToken()) {
			case StreamTokenizer.TT_EOF:
                        	break scan;
              		default:
                        	break;
			case StreamTokenizer.TT_WORD:
                        	String strRecord = st.sval;
                        	String strValue = "";
				if (strRecord.equalsIgnoreCase(new String("[variables]"))) {
					flag=1;
				} else if (strRecord.equalsIgnoreCase(new String("[regles]"))) {
					flag=2;
				} else {
			blong:		if (flag==1) { // définit les Variables
						Tk=new StringTokenizer(strRecord,":");
						String sTkn= new String(Tk.nextToken());
						RuleVariable aClass = new RuleVariable(sTkn);
						sTk=Tk.nextToken();
						//textArea2.appendText("-"+sTkn+"-\n");	
						aClass.setLabels(sTk) ;
						sTk=Tk.nextToken();
						aClass.setPromptText(sTk) ;
  						rb.variableList.put(aClass.name,aClass) ;
						symbols.put(sTkn,aClass); // ajoute la variable à la table des symboles	
					} else if (flag==2) { // définit les Règles
						Tk=new StringTokenizer(strRecord,":");
						nsTk=Tk.nextToken();
						ssTk=Tk.nextToken();
						Tks=new StringTokenizer(ssTk," ");
						// vecteur pour stoquer les tokens	
						Vector tk1 = new Vector();
						Vector sgn = new Vector();
						Vector tk2 = new Vector();

						while (Tks.hasMoreTokens()) {
						esTk=Tks.nextToken();
							if (esTk.indexOf("!=")==-1 ) {	
								Tke=new StringTokenizer(esTk,"=");
								sgn.addElement(cEquals);
							} else {
								Tke=new StringTokenizer(esTk,"!=");
								sgn.addElement(cNotEquals);
							}
							tk1.addElement(Tke.nextToken());	
							tk2.addElement(Tke.nextToken());	
						}
						// clause conséquence
						sTk=Tk.nextToken();
						if (sTk.indexOf("!=")==-1 ) {	
							Tke=new StringTokenizer(sTk,"=");
							sgn.addElement(cEquals);
						} else {
							Tke=new StringTokenizer(sTk,"!=");
							sgn.addElement(cNotEquals);
						}
						tk1.addElement(Tke.nextToken());
						if (!(symbols.containsKey(tk1.lastElement()))) {
							textArea2.appendText("Erreur de Syntaxe:"+tk1.lastElement()+" non defini !\n");
							tk1.removeElement(tk1.lastElement());	
							sgn.removeElement(sgn.lastElement());	
							break blong;	
						} 
						tk2.addElement(Tke.nextToken());	
						// Création de la clause en fonction du nombre d'arguments
						if (tk1.size()==2) {
							Rule aRule = new Rule(rb, nsTk,
								new Clause((RuleVariable)symbols.get(tk1.elementAt(0)), (Condition)sgn.elementAt(0),(String)tk2.elementAt(0)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(1)), (Condition)sgn.elementAt(1),(String)tk2.elementAt(1)));
						} else if (tk1.size()==3) {
							Rule aRule = new Rule(rb, nsTk,
								new Clause((RuleVariable)symbols.get(tk1.elementAt(0)), (Condition)sgn.elementAt(0),(String)tk2.elementAt(0)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(1)), (Condition)sgn.elementAt(1),(String)tk2.elementAt(1)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(2)), (Condition)sgn.elementAt(2),(String)tk2.elementAt(2)));
						} else if (tk1.size()==4) {
							Rule aRule = new Rule(rb, nsTk,
								new Clause((RuleVariable)symbols.get(tk1.elementAt(0)), (Condition)sgn.elementAt(0),(String)tk2.elementAt(0)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(1)), (Condition)sgn.elementAt(1),(String)tk2.elementAt(1)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(2)), (Condition)sgn.elementAt(2),(String)tk2.elementAt(2)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(3)), (Condition)sgn.elementAt(3),(String)tk2.elementAt(3)));
						} else if (tk1.size()==5) {
							Rule aRule = new Rule(rb, nsTk,
								new Clause((RuleVariable)symbols.get(tk1.elementAt(0)), (Condition)sgn.elementAt(0),(String)tk2.elementAt(0)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(1)), (Condition)sgn.elementAt(1),(String)tk2.elementAt(1)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(2)), (Condition)sgn.elementAt(2),(String)tk2.elementAt(2)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(3)), (Condition)sgn.elementAt(3),(String)tk2.elementAt(3)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(4)), (Condition)sgn.elementAt(4),(String)tk2.elementAt(4)));
						} else if (tk1.size()==6) {
							Rule aRule = new Rule(rb, nsTk,
								new Clause((RuleVariable)symbols.get(tk1.elementAt(0)), (Condition)sgn.elementAt(0),(String)tk2.elementAt(0)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(1)), (Condition)sgn.elementAt(1),(String)tk2.elementAt(1)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(2)), (Condition)sgn.elementAt(2),(String)tk2.elementAt(2)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(3)), (Condition)sgn.elementAt(3),(String)tk2.elementAt(3)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(4)), (Condition)sgn.elementAt(4),(String)tk2.elementAt(4)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(5)), (Condition)sgn.elementAt(5),(String)tk2.elementAt(5)));
						} else if (tk1.size()==7) {
							Rule aRule = new Rule(rb, nsTk,
								new Clause((RuleVariable)symbols.get(tk1.elementAt(0)), (Condition)sgn.elementAt(0),(String)tk2.elementAt(0)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(1)), (Condition)sgn.elementAt(1),(String)tk2.elementAt(1)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(2)), (Condition)sgn.elementAt(2),(String)tk2.elementAt(2)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(3)), (Condition)sgn.elementAt(3),(String)tk2.elementAt(3)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(4)), (Condition)sgn.elementAt(4),(String)tk2.elementAt(4)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(5)), (Condition)sgn.elementAt(5),(String)tk2.elementAt(5)),
								new Clause((RuleVariable)symbols.get(tk1.elementAt(6)), (Condition)sgn.elementAt(6),(String)tk2.elementAt(6)));
						} else {
							textArea2.appendText("Unknown rule: "+ssTk+"\n");

						}
					} else {
						textArea2.appendText("Unknown: "+strRecord+"\n");
					}
				}
		}
		}	
		is.close();

	} catch(Exception e) {
        	String message = e.toString();
        	 textArea2.appendText("Exception ..." + message);
        }

        } catch (MalformedURLException e) {
                String message = e.toString();
                 textArea2.appendText("Exception ..." + message);
        }
}

}

