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

import java.util.*;

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.*;

import osa.attribute.atgrammar.gui.images.*;

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

public class ATGrammarEditorPane
  extends JPanel
  {
  public static final Color TERMINALS_COLOR=new Color(0,255,0);
  public static final Color NON_TERMINALS_COLOR=new Color(0,0,255);
  public static final Color OUTPUTS_COLOR=new Color(255, 200, 0);

  public static final Color SELECTED_COLOR=new Color(128,128,255);
  public static final Color UNSELECTED_COLOR=new Color(255,255,255);


  private class ProductionsListSelectionListener
    implements ListSelectionListener
    {
    public void valueChanged(ListSelectionEvent e)
      {
      JList productions_list=(JList)e.getSource();
      int selected_index=productions_list.getSelectedIndex();
      if(selected_index>-1)
        {
        selected_grammar_production=grammar_reference.getProductionAt(selected_index);
        list_of_productions_model.setCursorRowAt(selected_index);
        }
      else
        {
        selected_grammar_production=null;
        }
      updateAssignmnentsPane();
      }
    }

  private class ProductionsListModel
    extends AbstractListModel
    {
    private Grammar grammar_reference;

    private int cursor_row=0;
    private int desirable_cursor_position=0;
    private int actual_cursor_position=0;

    private GrammarProduction current_production=null;

    public ProductionsListModel(Grammar grammar_reference)
      {
      this.grammar_reference=grammar_reference;
      }

    public void setCursorRowAt(int row)
      {
      current_production=grammar_reference.getProductionAt(row);
      if(current_production==null)
        {
        return;
        }
      int string_len=current_production.getRightPart().getLength();
      if(this.desirable_cursor_position>string_len)
        {
        actual_cursor_position=string_len;
        }
      else
        {
        actual_cursor_position=desirable_cursor_position;
        }
      cursor_row=row;
      }

    public void incrementCursorPosition()
      {
      if(current_production==null)
        {
        return;
        }
      if(actual_cursor_position<current_production.getRightPart().getLength())
        {
        actual_cursor_position++;
        }
      desirable_cursor_position=actual_cursor_position;
      }

    public void decrementCursorPosition()
      {
      if(actual_cursor_position>0)
        {
        actual_cursor_position--;
        }
      desirable_cursor_position=actual_cursor_position;
      }

    public int getCursorPosition()
      {
      return this.actual_cursor_position;
      }

    public Object getElementAt(int index)
      {
      return grammar_reference.getProductionAt(index);
      }

    public void insertSymbol(Symbol symbol)
      {
      if(current_production==null)
        {
        return;
        }
      SymbolsString right_part=current_production.getRightPart();

      Symbol new_symbol=(Symbol)symbol.clone();
      new_symbol.setOriginalName("");

      right_part.insertSymbolAt(actual_cursor_position,new_symbol);
      Grammar.getInstance().updateAssignmentsIndexes();
      Grammar.getInstance().updateProductions();
      incrementCursorPosition();
      }

   public void removeSymbol()
     {
     if(current_production==null)
       {
       return;
       }

     SymbolsString right_part=current_production.getRightPart();

     if(actual_cursor_position>0)
       {
       Symbol symbol=right_part.getSymbolAt(actual_cursor_position-1);
       if(symbol.getType()==Symbol.OUTPUT_SYMBOL)
         {
         right_part.deleteSymbolAt(actual_cursor_position-1);
         Grammar.getInstance().updateAssignmentsIndexes();
         Grammar.getInstance().updateProductions();
         Grammar.getInstance().updateAssignmentsLabels();
         decrementCursorPosition();
         }
       }
     }


    public int getSize()
      {
      if(grammar_reference!=null)
        {
        return grammar_reference.getProductionsCount();
        }
      return -1;
      }
    }

  private class ProductionsListCellRenderer
    implements ListCellRenderer
    {

    public Component getListCellRendererComponent
      (
      JList list,
      Object value,
      int index,
      boolean isSelected,
      boolean cellHasFocus
      )
      {
      if(value instanceof GrammarProduction)
        {
        GrammarProduction current_production;
        current_production=(GrammarProduction)value;

        JPanel cell_pane=new JPanel();
        cell_pane.setLayout(new FlowLayout(FlowLayout.LEFT,0,0));

        Symbol temp_symbol;
        JLabel temp_label;

        temp_symbol=current_production.getLeftPart();

        // left part of production
        temp_label=new JLabel();
        temp_label.setText(temp_symbol.toString()+" ");
        temp_label.setForeground(NON_TERMINALS_COLOR);
        cell_pane.add(temp_label);

        // --> sign
        temp_label=new JLabel();
        temp_label.setText("-->"+" ");
        temp_label.setForeground(Color.black);
        cell_pane.add(temp_label);


        int cursor_position=0;

        if(isSelected)
          {
          cell_pane.setBackground(SELECTED_COLOR);
          ProductionsListModel model =(ProductionsListModel)list.getModel();
          model.setCursorRowAt(index);
          cursor_position=model.getCursorPosition();
          }
        else
          {
          cell_pane.setBackground(UNSELECTED_COLOR);
          }

        // right part of production
        SymbolsString right_part=current_production.getRightPart();
        int right_part_len=right_part.getLength();
        int i=0;
        for(i=0;i<right_part_len;i++)
           {
           if(isSelected && i==cursor_position)
             {
             ImageIcon cursor_icon=ImageLoader.loadImage("cursor.gif");
             temp_label=new JLabel(cursor_icon);
             temp_label.setForeground(Color.magenta);
             cell_pane.add(temp_label);
             }


           temp_label=new JLabel();
           temp_symbol=right_part.getSymbolAt(i);

           temp_label.setText(temp_symbol.toString()+" ");
           switch(temp_symbol.getType())
                 {
                 case Symbol.NON_TERMINAL_SYMBOL:
                   temp_label.setForeground(NON_TERMINALS_COLOR);
                   break;
                 case Symbol.TERMINAL_SYMBOL:
                   temp_label.setForeground(TERMINALS_COLOR);
                   break;
                 case Symbol.OUTPUT_SYMBOL:
                   temp_label.setForeground(OUTPUTS_COLOR);
                   break;
                 default:
                 }
           cell_pane.add(temp_label);
           }

         if(isSelected && i==cursor_position)
           {
           ImageIcon cursor_icon=ImageLoader.loadImage("cursor.gif");
           temp_label=new JLabel(cursor_icon);
           temp_label.setForeground(Color.magenta);
           cell_pane.add(temp_label);
           }


        return cell_pane;
        }
      return new JLabel("Error!");
      }
    }

  private class ProductionsListKeyListener
    implements KeyListener
    {

    JList subscriber;

    public ProductionsListKeyListener(JList subscriber)
      {
      this.subscriber=subscriber;
      }

    public void keyTyped(KeyEvent e)
      {
//      System.err.println("typed "+e.getKeyCode());
      }

    public void keyPressed(KeyEvent e)
      {
      ProductionsListModel model=(ProductionsListModel)subscriber.getModel();
      if(model==null)
        {
        return;
        }

      int key_code=e.getKeyCode();
      switch(key_code)
            {
            case KeyEvent.VK_UP:
              System.err.println("pressed up");
              break;
            case KeyEvent.VK_DOWN:
              System.err.println("pressed down");
              break;
            case KeyEvent.VK_LEFT:
              System.err.println("pressed left");
              model.decrementCursorPosition();
              subscriber.updateUI();
              break;
            case KeyEvent.VK_RIGHT:
              System.err.println("pressed right");
              model.incrementCursorPosition();
              subscriber.updateUI();
              break;
            case KeyEvent.VK_ENTER:
              System.err.println("pressed enter");
              Symbol selected_symbol=getATGrammarPane().getDictionaryPane().getSelectedSymbol();
              if(selected_symbol!=null)
                {
                if(selected_symbol.getType()==Symbol.OUTPUT_SYMBOL)
                  {
                  model.insertSymbol(selected_symbol);
                  subscriber.updateUI();
                  }
                }
              break;
            case KeyEvent.VK_BACK_SPACE:
                System.err.println("pressed backspace");
                model.removeSymbol();
                subscriber.updateUI();
              break;
            }
      }

    public void keyReleased(KeyEvent e)
      {
//      System.err.println("released "+e.getKeyCode());
      }

    }


  private JList list_of_productions;
  private ProductionsListModel list_of_productions_model;
  private ProductionsListCellRenderer list_of_productions_cell_renderer;


  private Grammar grammar_reference;

  private GrammarProduction selected_grammar_production;


  BorderLayout borderLayout1 = new BorderLayout();
  JScrollPane list_scroll_pane = new JScrollPane();

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

    // preparing list cell renderer
    list_of_productions_cell_renderer=new ProductionsListCellRenderer();

    // preparing list_of_productions;
    list_of_productions=new JList();

    // setting list renderer
    list_of_productions.setCellRenderer(new ProductionsListCellRenderer());

    // setting list key_listener
    list_of_productions.addKeyListener(new ProductionsListKeyListener(list_of_productions));

    // setting list selection_listener
    list_of_productions.addListSelectionListener(new ProductionsListSelectionListener());

    //
    list_of_productions.setModel(new ProductionsListModel(grammar_reference));

    list_scroll_pane.setViewportView(list_of_productions);

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

  public void update()
    {
    // preparing list model
    list_of_productions_model=new ProductionsListModel(grammar_reference);
    list_of_productions.setModel(list_of_productions_model);
    repaint();
    }

  private void jbInit() throws Exception
    {
    this.setLayout(borderLayout1);
    this.add(list_scroll_pane, BorderLayout.CENTER);
    }

  ATGrammarPane at_grammar_pane=null;
  protected ATGrammarPane getATGrammarPane()
    {
    if(at_grammar_pane==null)
      {
      at_grammar_pane=ATGrammarTabPane.getInstance().getATGrammarPane();
      }
    return at_grammar_pane;
    }

  protected void updateAssignmnentsPane()
    {
    getATGrammarPane().getAssignmentsTablePane().setGrammarProductionToView(selected_grammar_production);
    }

  }