package icsDyn;


// JDK

import java.awt.Color;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.IOException;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import java.util.Enumeration;
import javax.swing.BorderFactory;
import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JMenuItem;
import javax.swing.JPanel;
import javax.swing.JPopupMenu;
import javax.swing.JScrollPane;
import javax.swing.JTree;
import javax.swing.JOptionPane;
import javax.swing.event.TreeSelectionEvent;
import javax.swing.event.TreeSelectionListener;
import javax.swing.tree.DefaultMutableTreeNode;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import javax.xml.parsers.ParserConfigurationException;
import org.xml.sax.SAXException;



/**
 * This panel displays the tree structure of the batch message
 * @author  Rick Rivello
 */
public class ICSTreePanel extends JPanel implements Observer, ActionListener, TreeSelectionListener{

    private static final long serialVersionUID = 1L;

    private JTree icsTree;
    private JScrollPane icstScrollPane;
    private JButton btnAddMOC;
    private JButton btnRemoveMOC;
    private JButton btnAddAttribute;
    private JButton btnAddNotification;
    private JButton btnAddBehaviour;
    private AddMOCDialog dlgAddMoc;   
    private ICSModel icsModel;
    private AddRemoveAttr addremattr; 
    private AddRemoveBehavior addrembehav;
    private AddRemoveNotification addremnoti; 
    private Enumeration expenum;

    public MOCNode pn;
    
    
    private JPopupMenu popUpMenu;
    private JMenuItem menuAddObj;
    private JMenuItem menuRemoveObj;
    private JMenuItem menuUpdateAttr;
    private JMenuItem menuUpdateBehav;
    private JMenuItem menuUpdateNotif;

    /**
     * Constructor
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    public ICSTreePanel() throws ParserConfigurationException, SAXException, IOException {
    	
    //initialize the pop up menu
    popUpMenu = new JPopupMenu();
    menuAddObj = new JMenuItem("Add MOC...");
    menuRemoveObj = new JMenuItem("Remove MOC");
    menuUpdateAttr = new JMenuItem("Update Attributes...");
    menuUpdateBehav = new JMenuItem("Update behaviours...");
    menuUpdateNotif = new JMenuItem("Update notifications...");
    
    menuAddObj.addActionListener(this);
    menuRemoveObj.addActionListener(this);
    menuUpdateAttr.addActionListener(this);
    menuUpdateBehav.addActionListener(this);
    menuUpdateNotif.addActionListener(this);
    
    popUpMenu.add(menuAddObj);
    popUpMenu.add(menuRemoveObj);
    popUpMenu.add(menuUpdateAttr);
    popUpMenu.add(menuUpdateBehav);
    popUpMenu.add(menuUpdateNotif);
    	
	setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));

	JPanel p0 = new JPanel();
	p0.setLayout(new BoxLayout(p0, BoxLayout.LINE_AXIS));
	icsTree = new JTree(new Vector());
	icsTree.addTreeSelectionListener(this);
	icsTree.addMouseListener(new MouseAdapter(){
		public void mousePressed(MouseEvent e) {
			displayMenu(e);			
		}
		public void mouseReleased(MouseEvent e) {
			displayMenu(e);			
		}		
	});
	icsTree.addKeyListener(new KeyAdapter(){
		public void keyPressed(KeyEvent arg0) {
			keyManage(arg0);
			
		}	
	});
	
	icstScrollPane = new JScrollPane(icsTree);
	icstScrollPane.setPreferredSize(new Dimension(100, 100));
	p0.add(icstScrollPane);
	
	JPanel p1 = new JPanel();
	p1.setLayout(new BoxLayout(p1, BoxLayout.PAGE_AXIS));
	
	btnAddMOC = new JButton("Add MOC");
    btnAddMOC.setBackground(new Color(204, 204, 255));
    btnAddMOC.addActionListener(this);
	p1.add(btnAddMOC);
	p1.add(Box.createRigidArea(new Dimension(0, 5)));
	
	btnRemoveMOC = new JButton("Remove MOC");
	btnRemoveMOC.setBackground(new Color(204, 204, 255));
	btnRemoveMOC.setPreferredSize(new Dimension(180,30));
	btnRemoveMOC.addActionListener(this);
	p1.add(btnRemoveMOC);
	p1.add(Box.createRigidArea(new Dimension(0, 5)));    
   
	btnAddAttribute = new JButton("Update attributes...");
    btnAddAttribute.setBackground(new Color(204, 204, 255));
    btnAddAttribute.addActionListener(this);
    p1.add(btnAddAttribute);
    p1.add(Box.createRigidArea(new Dimension(0, 5)));   
      
  
    btnAddBehaviour = new JButton("Update behaviours...");
    btnAddBehaviour.setBackground(new Color(204, 204, 255));
    btnAddBehaviour.addActionListener(this);
    p1.add(btnAddBehaviour);
    p1.add(Box.createRigidArea(new Dimension(0, 5)));
    
    btnAddNotification = new JButton("Update notifications...");
    btnAddNotification.setBackground(new Color(204, 204, 255));
    btnAddNotification.addActionListener(this);
    p1.add(btnAddNotification);
    //p1.add(Box.createRigidArea(new Dimension(0, 5)));

	add(p0);
	add(Box.createRigidArea(new Dimension(0, 5)));
	add(p1);
       // add(Box.createRigidArea(new Dimension(0, 5)));
	
	setBorder(BorderFactory.createEmptyBorder(5,5,5,5));

	//dlgAddMoc = new AddMOCDialog(null);
	init();


    }

    /**
     * Handles a click event
     * @param evt The event
     * @throws IOException
     * @throws SAXException
     * @throws ParserConfigurationException
     */
    public void actionPerformed(ActionEvent evt) {
        expenum = TreeExpansionUtils.saveExpansionState(icsTree);
    	TreePath path = icsTree.getSelectionPath();
    	DefaultMutableTreeNode node = (DefaultMutableTreeNode)icsTree.getLastSelectedPathComponent();

        int nodeChildCount1 = node.getChildCount();
	if(evt.getSource() == btnAddMOC || evt.getSource() == menuAddObj) {
	   dlgAddMoc = new AddMOCDialog(null);
           dlgAddMoc.setICSModel(icsModel);
           icsModel.addObserver(dlgAddMoc);
	   dlgAddMoc.init(node);                
	   dlgAddMoc.pack();
           // Center the window
           dlgAddMoc.setLocationRelativeTo(this);
           dlgAddMoc.setVisible(true);
           int nodeChildCount2 = node.getChildCount();
           if (nodeChildCount1 != nodeChildCount2) {
              icsTree.expandPath(new TreePath(node.getPath()));
              expenum = TreeExpansionUtils.saveExpansionState(icsTree);
           }
	   DefaultTreeModel model = new DefaultTreeModel(icsModel.getTree());
           icsTree.setModel(model);
           btnAddMOC.setEnabled(false);
           btnRemoveMOC.setEnabled(false);
           icsModel.setGenerateEnable(true);		
	}

	else if(evt.getSource() == btnRemoveMOC || evt.getSource() == menuRemoveObj) {	    

	    if(node != null) {
                if (node.toString().equals("DIM")) {
                   String msg = "The ROOT NODE "+node.toString()+" CANNOT BE REMOVED because an INVALID ICS will be generated";
                   String title = "REMOVE MOC WARNING MESSAGE";
                   JOptionPane.showConfirmDialog(this, msg, title,JOptionPane.DEFAULT_OPTION,JOptionPane.WARNING_MESSAGE);
                }
                else if ((node.toString().equals("Composite_Single_Bed_MDS")) && (node.getParent().toString().equals("DIM")) ||
                    (node.toString().equals("Simple_MDS")) && (node.getParent().toString().equals("DIM")) ||
                    (node.toString().equals("Hydra_MDS")) && (node.getParent().toString().equals("DIM"))) {
                   String msg = "The NODE "+node.toString()+" CANNOT BE REMOVED because an INVALID ICS will be generated";
                   String title = "REMOVE MOC WARNING MESSAGE";
                   JOptionPane.showConfirmDialog(this, msg, title,JOptionPane.DEFAULT_OPTION,JOptionPane.WARNING_MESSAGE);
                }
                else {
		   path = path.getParentPath();
		   icsModel.removeMOC(node);
		   DefaultTreeModel model = new DefaultTreeModel(icsModel.getTree());
		   icsTree.setModel(model);
	           btnAddMOC.setEnabled(false);
	           btnRemoveMOC.setEnabled(false);
	           icsModel.setGenerateEnable(true);
                }
	    }

	}
        else if(evt.getSource() == btnAddAttribute || evt.getSource() == menuUpdateAttr) {
            
            if(node != null) {
                Vector defvmoc = icsModel.getVMoc();
                Vector dynvmoc = icsModel.getcurVMoc();
                addremattr = new AddRemoveAttr(this);
                addremattr.setICSModel(icsModel);
                addremattr.mn(addremattr,dynvmoc,defvmoc,node);
                DefaultTreeModel model = new DefaultTreeModel(icsModel.getTree());
                icsTree.setModel(model);
            }
        }
        else if(evt.getSource() == btnAddBehaviour || evt.getSource() == menuUpdateBehav) {
            
            if(node != null) {
                Vector defvmoc = icsModel.getVMoc();
                Vector dynvmoc = icsModel.getcurVMoc();
                addrembehav = new AddRemoveBehavior(this);
                addrembehav.setICSModel(icsModel);
                addrembehav.mn(addrembehav,dynvmoc,defvmoc,node);
                DefaultTreeModel model = new DefaultTreeModel(icsModel.getTree());
                icsTree.setModel(model);
            }	
        }
        else if(evt.getSource() == btnAddNotification || evt.getSource() == menuUpdateNotif) {
            
            if(node != null) {
                Vector defvmoc = icsModel.getVMoc();
                Vector dynvmoc = icsModel.getcurVMoc();
                addremnoti = new AddRemoveNotification(this);
                addremnoti.setICSModel(icsModel);
                addremnoti.mn(addremnoti,dynvmoc,defvmoc,node);
                DefaultTreeModel model = new DefaultTreeModel(icsModel.getTree());
                icsTree.setModel(model);
            }        	
        }
	
        TreeExpansionUtils.loadExpansionState(icsTree, expenum);
        icsTree.setSelectionPath(path);
	
    }
    private void removeNode(DefaultMutableTreeNode node) {
    	if(node != null) {
    		icsModel.removeMOC(node);
    		DefaultTreeModel model = new DefaultTreeModel(icsModel.getTree());
    		icsTree.setModel(model);
    		icsModel.fireEvent(new MVCArg("node tree", (String)null));
    	    }
    	    btnAddMOC.setEnabled(false);
    	    btnRemoveMOC.setEnabled(false);
    	    icsModel.setGenerateEnable(true);
    	    
	}

	/**
     * Handles a tree click event
     * @param evt The event
     */
    public void valueChanged(TreeSelectionEvent evt) {
    	
	btnAddMOC.setEnabled(false);
	btnRemoveMOC.setEnabled(false);
        btnAddAttribute.setEnabled(true);
        btnAddBehaviour.setEnabled(true);
        btnAddNotification.setEnabled(true);
	DefaultMutableTreeNode node = (DefaultMutableTreeNode)icsTree.getLastSelectedPathComponent();
	icsModel.fireEvent(new MVCArg("node tree", node));
	if(node == null) {
	    btnAddMOC.setEnabled(true);
	    btnRemoveMOC.setEnabled(true);
        btnAddAttribute.setEnabled(true);
        btnAddBehaviour.setEnabled(true);
        btnAddNotification.setEnabled(true);
	    icsModel.fireEvent(new MVCArg("nodeBlank",""));
	    return;
	}
	btnAddMOC.setEnabled(true);
    btnRemoveMOC.setEnabled(true);
    btnAddAttribute.setEnabled(true);
    btnAddBehaviour.setEnabled(true);
    btnAddNotification.setEnabled(true);
    
	Object nodeInfo = node.getUserObject();
	if(nodeInfo instanceof MOCNode) {
	}
	icsModel.fireEvent(new MVCArg("node", nodeInfo));
    }

    /**
     * MVC
     * @param o The observable object
     * @param arg An argument passed to the notifyObservers method
     */
    public void update(Observable o, Object arg) {
        if(o instanceof ICSModel) {
		if("tree status".equals(((MVCArg)arg).getName())) {
			TreePath path = icsTree.getSelectionPath();
                        expenum = TreeExpansionUtils.saveExpansionState(icsTree);
			DefaultTreeModel model = new DefaultTreeModel(icsModel.getTree());
			icsTree.setModel(model);
			icsTree.setSelectionPath(path);
                        TreeExpansionUtils.loadExpansionState(icsTree, expenum);
		}
		if("mdsType".equals(((MVCArg)arg).getName())) {
			
		    try {
			DefaultTreeModel model = new DefaultTreeModel(icsModel.getMainTree(((MVCArg)arg).getValue()));
			icsTree.setModel(model);
			icsTree.setRootVisible(true);
			icsModel.setGenerateEnable(true);
		    }
		    catch(ParserConfigurationException pce) {
			System.err.println("ParserConfigurationException " + pce.getMessage());
			pce.printStackTrace();
		    }
		    catch(SAXException saxe) {
			System.err.println("SAXException " + saxe.getMessage());
			saxe.printStackTrace();
		    }
		    catch(IOException ioe) {
			System.err.println("IOException " + ioe.getMessage());
			ioe.printStackTrace();
		    }
		}
	    
		 if("init".equals(((MVCArg)arg).getName())) {
		    init();
		}
	    }
            
    }
	
    /**
     * Set the model
     * @param model The model
     */
   public void setICSModel(ICSModel model) {
   	icsModel = model;
   	//dlgAddMoc.setICSModel(model);
    }

    /**
     * Init the panel
     */
    public void init() {
    	icsTree.setModel(null);    	
    	btnAddMOC.setEnabled(false);
    	btnRemoveMOC.setEnabled(false);
        btnAddAttribute.setEnabled(false);
        btnAddBehaviour.setEnabled(false);
        btnAddNotification.setEnabled(false);        
    }
    private void displayMenu(MouseEvent e) {
    	if(icsTree != null && e.isPopupTrigger()){
    		try {
    			
    			TreePath path = icsTree.getPathForLocation(e.getX(),e.getY());
    			icsTree.setSelectionPath(path);
    			popUpMenu.show(e.getComponent(), e.getX(), e.getY());
    		} catch (NullPointerException ex) {
//    		This means the user did not click on a node
    		}
            
    	}
		
	}    

	private void keyManage(KeyEvent arg0) {
		DefaultMutableTreeNode node = (DefaultMutableTreeNode)icsTree.getLastSelectedPathComponent();
		if(arg0.getKeyCode() == KeyEvent.VK_DELETE && node != null){
			expenum = TreeExpansionUtils.saveExpansionState(icsTree);
	    	TreePath path = icsTree.getSelectionPath();
			removeNode(node);
			TreeExpansionUtils.loadExpansionState(icsTree, expenum);
	        icsTree.setSelectionPath(path.getParentPath());
		}		
	}	
    
}
