import java.awt.*;
import java.applet.*;
import java.lang.String;

public class Rules extends Applet {
    protected TextField right_field;    
    protected TextField left_field;  
    protected List my_rules;

    protected TextArea comments;
    
    protected Label info_rules;
    protected Label arrow;
    protected Button butt_add2;
    protected Button butt_edit2;
    protected Button butt_delete2;
    protected Button check;    
 
           
    public void init(){ 
         setBackground(new Color(255, 255, 180)); //light yellow
 
         //init ALL Components
	 
         //text labels
	 info_rules = new Label ("Enter new rule"+"   ");
	 arrow = new Label ("-->");              
         Label info3 = new Label ( "HERE YOU CAN CHANGE GRAMMAR");
         info3.setForeground(Color.red);
         
        //input field for new rules         
	 left_field=new TextField(5);     
         left_field.setText("");
         right_field=new TextField(7);     
         right_field.setText(""); 
         //buttons
         butt_add2=new Button("Add");
         butt_edit2=new Button("Edit");
         butt_delete2=new Button("Delete");
         check=new Button("Are rules wellformed?");
         
        //create list with some rules 
        my_rules= new List(11,false);
        my_rules.addItem("S --> NP VP");                  
	my_rules.addItem("NP --> n");
	my_rules.addItem("NP --> det n");
	my_rules.addItem("NP --> det adj n");
	my_rules.addItem("VP --> vi");    
        my_rules.addItem("VP --> vi PP"); 
        my_rules.addItem("VP --> vt NP"); 
	my_rules.addItem("VP --> vt NP PP");
        my_rules.addItem("PP --> prep NP");
        my_rules.addItem("PP --> prep NP PP");

        comments = new TextArea(3,40); 
        comments.setEditable(false);

       //ORGANIZE LAYOUT !!!!!!!!!!!!!!!!!!!!!!!!
      
       //  setBackground(Color.blue);
	
        GridBagLayout gbl = new GridBagLayout();
	GridBagConstraints gbc = new GridBagConstraints();
        setLayout(gbl); 
        
	gbc.gridwidth = GridBagConstraints.REMAINDER;	
        gbl.setConstraints(info3,gbc);
	add(info3);
       
        gbc.weighty = 2;
	gbc.gridwidth = GridBagConstraints.REMAINDER;	
        gbc.fill=GridBagConstraints.BOTH; 
        gbl.setConstraints(my_rules,gbc);
	add(my_rules);
	
        gbc.weighty = 0;
        Panel rule_field = new Panel();
	gbc.gridwidth = GridBagConstraints.REMAINDER;       
	gbl.setConstraints(rule_field,gbc);
	add(rule_field);
	rule_field.add(info_rules);
        rule_field.add(left_field);
        rule_field.add(arrow);             
        rule_field.add(right_field);
        
	Panel Butt = new Panel();
	gbc.gridwidth = GridBagConstraints.REMAINDER;       
	gbl.setConstraints(Butt,gbc);
	add(Butt);
           
           Butt.setLayout(new FlowLayout());
	   Butt.add(butt_add2);       
	   Butt.add(butt_edit2);
           Butt.add(butt_delete2);      
        
	gbc.gridwidth = GridBagConstraints.REMAINDER;       
        gbc.fill=GridBagConstraints.NONE; 
	gbl.setConstraints(check,gbc);
	add(check); 

        gbc.weighty = 1;
	gbc.weightx = 1;	
	gbc.gridwidth = GridBagConstraints.REMAINDER;
        gbc.fill=GridBagConstraints.BOTH; 
        gbl.setConstraints(comments,gbc);
	add(comments);
      } 
    
   //POSSIBLE ACTIONS 
    
    public boolean action(Event evt, Object whatAction){                       
       if( (evt.target == right_field) ||
           (evt.target == butt_add2)){                
               if(ruleOK()){
                  my_rules.addItem(left_field.getText()+" --> "+right_field.getText() );
                  check_and_order_rules();
                  set_init_state();
                  return true;
               }else return false;
                 
       }else if((evt.target == butt_delete2) && (my_rules.getSelectedItem() != null)){
                my_rules.delItem(my_rules.getSelectedIndex());
                return true; 
       }else if((evt.target == butt_edit2) && (my_rules.getSelectedItem() != null)){                 
                 left_field.setText(restore_left(my_rules.getSelectedItem()));
                 right_field.setText(restore_right(my_rules.getSelectedItem()));
                 my_rules.delItem(my_rules.getSelectedIndex());      
                 return true; 
       }else if(evt.target == check){
                check_and_order_rules();       
                return true; 
       }else return false;
    }

//this function checks the correctness of the rule's form
                  
    public boolean ruleOK(){
            if(!rightOK() && !leftOK() ) {
               info_rules.setText("Enter new rule"+"!!!"); 
               return false;
            }else if( (leftOK() && !rightOK()) || (!leftOK() && rightOK())){              
               info_rules.setText("Rule malformed"+"!!!");      
               return false; 
            }else{
               info_rules.setText("Enter new rule"+"   "); 
               return true;
            }
    }		

//return the rule input fields to the initial state
   public void set_init_state(){
            right_field.setText("");
            left_field.setText("");
	    left_field.show();                  
            right_field.show();
            info_rules.setText("Enter new rule"+"   ");         
    } 

//check the form of the rule

   public boolean rightOK(){
           String right = right_field.getText();
           right=right.trim();
           boolean right_good=false;             
           for(int i=0; i<right.length(); i++){ 
               if(Character.isLetterOrDigit(right.charAt(i))==true){
                  right_good=true;
               }        
           }
           if(right.equals("") || right_good==false)
              return false;
           else return true;
   }          

   public boolean leftOK(){
           String left = left_field.getText();
           left=left.trim();
           boolean left_good=false;             
           for(int i=0; i<left.length(); i++){ 
               if(Character.isLetterOrDigit(left.charAt(i))==true){

                  left_good=true;
               }        
           }           
           if(left.equals("") || left_good==false)
              return false;
           else return true;
   }          
   
   //get the left part of the rule

   public String restore_left(String rule){
            int arrow=rule.indexOf("-->");
            String left=rule.substring(0,arrow);
            left=left.trim(); 
            return left;
   } 
   
   //get the right part of the rule

   public String restore_right(String rule){
            int arrow=rule.indexOf("-->");
            String right=rule.substring(arrow+3, rule.length());
            right=right.trim();
            return right;
   } 
 

//  check the wellformedness and make top-down order

   public void check_and_order_rules(){    //rules with initial symbol (only on the left side) are found
                               //then right part of each rule is checked and ordered
        comments.setText("");

        int next_free_line=0; //left_part index, where the rule can be placed
        int line_checked=0; //right_part index, from where the constituents are taken
        
        next_free_line=find_and_order_init_symbol(); //find all rules with init_symbols and return
                                              // number of them      
        if(next_free_line==0){
           comments.appendText("No top constituent!");          
        }
        
        
        String curr_right;
        String curr_const;
        int next_blank;
        boolean is_new;
        boolean found_lex;
        boolean found_left; 
        Non_Terminals my_non_terminals=new Non_Terminals();

        while(line_checked<my_rules.countItems()){              
              
            curr_right=restore_right(my_rules.getItem(line_checked));               
            curr_right =curr_right+" ";
     
            while ( !curr_right.equals(" ") ) {
	            
                   next_blank = curr_right.indexOf(" ");

      	           //take next constituent from input
                   curr_const = curr_right.substring(0, next_blank);                  

                   found_left=false; 
        
                   for(int i=next_free_line; i < my_rules.countItems(); i++){
    
                       if(restore_left(my_rules.getItem(i)).equals(curr_const)){
                          found_left=true;
     
                   //move found rule
                          my_rules.addItem(my_rules.getItem(i), next_free_line);              
                          my_rules.delItem(i+1);
                          next_free_line++;
                       }
                    }
                 
                    
                   
                   if(found_left){
                       my_non_terminals.new_non_term(curr_const);        
                   } //put the new non_term into the store
                    
                   is_new=my_non_terminals.is_new_non_term(curr_const);   
                   
                   found_lex=check_lexicon(curr_const);

  
                   if(!found_left && is_new && !found_lex){
                       comments.appendText("Warning: "+curr_const+" is neither non-terminal nor found in Lexicon\n");                                   
                
                   }    
              
                   if(found_left && found_lex){
                       comments.appendText("Error: "+curr_const+" is part of speech in Lexicon and non-terminal constituent\n");                  
                   }          
               
                   curr_right = curr_right.substring(next_blank);
                   curr_right = curr_right.trim()+" ";
               } //end current_constituent analyzing
           
           line_checked++; //end current line (right_part) analyzing
        }    
        //everything OK
       if(comments.getText().equals("")){
           comments.setText("Rules are wellformed");                      
        } 
   }

   protected int find_and_order_init_symbol(){
         
         String curr_right; 
         String curr_left;     
         boolean is_init;
         int how_many_init=0;

         for(int i=0; i< my_rules.countItems(); i++){
               curr_left=restore_left(my_rules.getItem(i));

	       is_init = true;
               for( int j=0; (j< my_rules.countItems()) && is_init; j++ ){
                   curr_right=restore_right(my_rules.getItem(j))+" ";
  
                   is_init = ( curr_right.indexOf(curr_left) < 0 );
               }
           
               if(is_init){                  
                  my_rules.addItem(my_rules.getItem(i), 0);              
                  my_rules.delItem(i+1);
                  how_many_init++;                  
               } 
         }
      
         return how_many_init;
    } 

//look whether the constituent is terminal (is in lexicon)
         protected boolean check_lexicon(String curr_const) {
        
             List curr_lexicon;
             boolean found_lex=false;
             curr_const=curr_const.trim();               
           
             LexRulesInput ancestor = (LexRulesInput) getParent();
             curr_lexicon=ancestor.myLexicon.my_lexicon;           
           
             int j=0; //number of the next speechpart's string in speechpart's array
             for(int i=0; i< curr_lexicon.countItems(); i++){
                   
             if( ( ( ancestor.myLexicon.restore_LexItem 
                       (curr_lexicon.getItem(i))).get_speechpart()).equals(curr_const) ){
                  found_lex=true;
	       }
             } 
          return found_lex;
         } 
   


}
