package osa.attribute.atgrammar.gui.panels.derivation_panels;

import java.util.*;
import java.io.*;


import javax.swing.*;
import javax.swing.event.*;

import java.awt.*;
import java.awt.event.*;

import osa.attribute.atgrammar.grammar.*;
import osa.attribute.atgrammar.grammar.symbols.*;

/**
 * <p>Title: </p>
 * <p>Description: </p>
 * <p>Copyright: </p>
 * <p>Company: </p>
 * @author not attributable
 * @version
 */

public class DerivationPane
  extends JPanel
  {
  protected class AlternativeProductionsListModel
    extends AbstractListModel
    {
    ArrayList alternative_productions=null;

    public AlternativeProductionsListModel(NonTerminalSymbol left_part)
      {
      if(left_part!=null)
        {
        System.err.println("Левая часть 1"+left_part.toString());
        alternative_productions=new ArrayList();

        GrammarProduction temp_production;
        int len=grammar_reference.getProductionsCount();
        for(int i=0;i<len;i++)
           {
           temp_production=grammar_reference.getProductionAt(i);

           if(left_part.getOriginalName().equals(temp_production.getLeftPart().getOriginalName()))
             {
             alternative_productions.add(temp_production);
             }
           }
        }
      }

    public int getSize()
      {
      if(alternative_productions!=null)
        {
        return alternative_productions.size();
        }
      return 0;
      }

    public Object getElementAt(int index)
      {
      if(alternative_productions!=null)
        {
        return alternative_productions.get(index);
        }
      return null;
      }
    }

  protected class NextStepBtnActionListener
    implements ActionListener
    {
    public void actionPerformed(ActionEvent e)
      {

/*      GrammarProduction temp_production;
      Symbol temp_symbol;
      Attribute temp_attribute;
      int prod_len=grammar_reference.getProductionsCount();
      int string_len;
      int attrs_len;
      for(int productions_counter=0;productions_counter<prod_len;productions_counter++)
         {
         temp_production=grammar_reference.getProductionAt(productions_counter);

         temp_production.updateProduction();

         temp_symbol=temp_production.getLeftPart();
         System.err.print(temp_symbol.toString());

         attrs_len=temp_symbol.getAttrubutesCount();

         for(int attrs_counter=0;attrs_counter<attrs_len;attrs_counter++)
            {
            temp_attribute=temp_symbol.getAttributeAt(attrs_counter);
            System.err.print("."+temp_attribute.toString());
            }

         System.err.print(" ::= ");

         string_len=temp_production.getRightPart().getLength();
         for(int symbol_counter=0;symbol_counter<string_len;symbol_counter++)
            {
            temp_symbol=temp_production.getRightPart().getSymbolAt(symbol_counter);

            System.err.print(temp_symbol.toString());

            attrs_len=temp_symbol.getAttrubutesCount();

            for(int attrs_counter=0;attrs_counter<attrs_len;attrs_counter++)
               {
               temp_attribute=temp_symbol.getAttributeAt(attrs_counter);
               System.err.print("."+temp_attribute.toString());
               }

            }

         System.err.println("");
         }

/*
      grammar_reference.getDictionary().resetAllCounters();

      NonTerminalSymbol symbol;




      symbol=(NonTerminalSymbol)grammar_reference.getInitialSymbol().getOriginalReference();
      for(int i=0;i<100;i++)
         {
         symbol=(NonTerminalSymbol)symbol.clone();

         System.err.print("-- "+symbol.toString());

         for(int j=0;j<symbol.getAttrubutesCount();j++)
            {
            System.err.print("."+symbol.getAttributeAt(j).toString());
            }
         System.err.print("\n");
         }*/






      Symbol temp_symbol;
      Attribute temp_attribute;
      int prod_len=grammar_reference.getProductionsCount();
      int string_len;
      int attrs_len;
      string_len=derivation_string.getLength();
      for(int symbol_counter=0;symbol_counter<string_len;symbol_counter++)
         {
         temp_symbol=derivation_string.getSymbolAt(symbol_counter);

         System.err.print(temp_symbol.toString());

         attrs_len=temp_symbol.getAttrubutesCount();

         for(int attrs_counter=0;attrs_counter<attrs_len;attrs_counter++)
            {
            temp_attribute=temp_symbol.getAttributeAt(attrs_counter);
            System.err.print("."+temp_attribute.toString());

            System.err.print("["+temp_attribute.getDeferredAssignments().size()+"]");


            }

         }














      evaluateCurrentSymbol();
      }
    }

  JLabel productions_lst_lbl = new JLabel();
  JScrollPane productions_lst_scroll_pane = new JScrollPane();
  JList productions_list = new JList();
  DerivationStringPanel derivation_string_panel = new DerivationStringPanel();
  JLabel derivation_string_lbl = new JLabel();
  JButton next_step_btn = new JButton();
  JScrollPane derivation_string_scroll_pane = new JScrollPane();
  JPanel buttons_panel = new JPanel();
  GridLayout gridLayout1 = new GridLayout();
  Component component1;
  Component component2;
  GridBagLayout gridBagLayout1 = new GridBagLayout();


  protected Grammar grammar_reference;

  protected DerivationString derivation_string;

  public DerivationPane(Grammar grammar_reference)
    {
    this.grammar_reference=grammar_reference;

    productions_list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);

    next_step_btn.addActionListener(new NextStepBtnActionListener());
    next_step_btn.setEnabled(false);


    try{
       jbInit();
       }
    catch(Exception e)
       {
       e.printStackTrace();
       }
    }

  private void jbInit()
    throws Exception
    {
    component1 = Box.createHorizontalStrut(8);
    component2 = Box.createHorizontalStrut(8);
    productions_lst_lbl.setText("Список альтернативных продукций:");
    this.setLayout(gridBagLayout1);
    derivation_string_lbl.setText("Цепочка вывода:");
    next_step_btn.setText("Следующий шаг");

    buttons_panel.setLayout(gridLayout1);
    gridLayout1.setColumns(4);
    gridLayout1.setHgap(5);
    gridLayout1.setVgap(5);
    this.add(productions_lst_lbl,   new GridBagConstraints(0, 0, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
    this.add(productions_lst_scroll_pane,     new GridBagConstraints(0, 1, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
    this.add(derivation_string_lbl,   new GridBagConstraints(0, 2, 1, 1, 0.0, 0.0
            ,GridBagConstraints.WEST, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
    this.add(derivation_string_scroll_pane,       new GridBagConstraints(0, 3, 1, 1, 1.0, 1.0
            ,GridBagConstraints.CENTER, GridBagConstraints.BOTH, new Insets(5, 5, 5, 5), 0, 0));
    derivation_string_scroll_pane.getViewport().add(derivation_string_panel, null);
    productions_lst_scroll_pane.getViewport().add(productions_list, null);
    this.add(buttons_panel,    new GridBagConstraints(0, 4, 1, 1, 1.0, 0.0
            ,GridBagConstraints.CENTER, GridBagConstraints.HORIZONTAL, new Insets(5, 5, 5, 5), 0, 0));
    buttons_panel.add(component1, null);
    buttons_panel.add(component2, null);
    buttons_panel.add(next_step_btn, null);
    }

  public void setSymbolLexicalValue( TerminalSymbol symbol )
    {
    if(symbol.getDefaultLexicalValue()!=null)
      {
      symbol.setLexicalValue(symbol.getDefaultLexicalValue());

      }
    else
      {
      String value=null;
      value = JOptionPane.showInputDialog(this,
                                          "Введите лексическое значение для терминала:",
                                          "");

       while(value==null)
            {
            JOptionPane.showMessageDialog(this,
                                          "Лексическое значение должно быть задано!",
                                          "Ошибка!",
                                          JOptionPane.WARNING_MESSAGE);
            value = JOptionPane.showInputDialog(this,
                                                "Введите лексическое значение для терминала:",
                                                "");
            }
      }
    }


  public void evaluateCurrentSymbol()
    {
    Symbol current_symbol;
    current_symbol=derivation_string.getCurrentSymbol();

    switch(current_symbol.getType())
          {
          case Symbol.NON_TERMINAL_SYMBOL:
            GrammarProduction selected_production;
            selected_production=(GrammarProduction)productions_list.getSelectedValue();
            if(selected_production==null)
              {
              JOptionPane.showMessageDialog(this,
                                            "Выберите альтернативную продукцию!",
                                            "Ошибка!",
                                            JOptionPane.WARNING_MESSAGE);
              return;
              }
            current_symbol.evaluate();
            derivation_string.executeSubstitution(selected_production);
            break;
          case Symbol.TERMINAL_SYMBOL:
            setSymbolLexicalValue((TerminalSymbol)current_symbol);
            derivation_string.moveToNextSymbol();
            break;
          case Symbol.OUTPUT_SYMBOL:
            current_symbol.evaluate();
            derivation_string.moveToNextSymbol();
            break;
          default:
          }

    current_symbol=derivation_string.getCurrentSymbol();
    if(current_symbol.getType()==Symbol.NON_TERMINAL_SYMBOL)
      {
      productions_list.setModel(new AlternativeProductionsListModel((NonTerminalSymbol)current_symbol));
      }
    else
      {
      productions_list.setModel(new AlternativeProductionsListModel(null));
      }
    derivation_string_panel.setModel(derivation_string);
    }

  public void startDerivation()
    {
    if(grammar_reference.getInitialSymbol()==null)
      {
      JOptionPane.showMessageDialog(this,"Грамматика пуста!","Ошибка!!!",JOptionPane.ERROR_MESSAGE);
      productions_list.setModel(new AlternativeProductionsListModel(null));
      derivation_string_panel.setModel(null);
      }
    else
      {
      derivation_string=new DerivationString(grammar_reference);
      derivation_string_panel.setModel(derivation_string);
      productions_list.setModel(new AlternativeProductionsListModel((NonTerminalSymbol)derivation_string.getCurrentSymbol()));
      next_step_btn.setEnabled(true);
      }
    }

  public void resetDerivation()
    {
    productions_list.setModel(new AlternativeProductionsListModel(null));
    derivation_string_panel.setModel(null);
    next_step_btn.setEnabled(false);
    }
  }