package icsDyn;
 
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Component;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.Insets;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Arrays;
import java.util.Iterator;
import java.util.Observable;
import java.util.Observer;
import java.util.Vector;
import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JList;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JOptionPane;
import javax.swing.ListCellRenderer;
import javax.swing.ListModel;
import javax.swing.tree.DefaultMutableTreeNode;

/**
 * This class allows the user adding or removing notifications to an object
 * @author  Rick Rivello
 */
public class AddRemoveNotification extends JPanel implements ActionListener, Observer{

  private static final long serialVersionUID = 1L;

  private static final Insets EMPTY_INSETS = new Insets(0, 0, 0, 0);
  private static final String ADD_BUTTON_LABEL = "Add >>";
  private static final String REMOVE_BUTTON_LABEL = "<< Remove";
  private static final String DEFAULT_SOURCE_CHOICE_LABEL = "Available Notifications";
  private static final String DEFAULT_DEST_CHOICE_LABEL = "Notifications Selected";
  private JLabel sourceLabel;
  private JList sourceList;
  private SortedListModel sourceListModel;
  private JList destList;
  private SortedListModel destListModel;
  private JLabel destLabel;
  private JButton addButton;
  private JButton removeButton;
  private JButton btnClose;
  private JButton btnAddChanges;
  private JButton btnAddPrivate;
  private Vector<NotificationNode> vectPrivate;
  private JFrame f;

  private ICSModel icsModel;  
  private Component parent;

  Vector dynnoti;
  Vector defnoti;
  MOCNode tempmoc;
  MOCNode defmocnode;
  MOCNode dynmocnode;
  DefaultMutableTreeNode cNode;

  String[] selectedDyn;

  public AddRemoveNotification(Component p) {
	parent = p;
	vectPrivate = new Vector<NotificationNode>();
    init();
  }

  public void setICSModel (ICSModel model) {
    icsModel = model;
    icsModel.addObserver(this);
  }

  public void mn(AddRemoveNotification notifications, Vector dynvmoc, Vector defvmoc,DefaultMutableTreeNode currentNode) {

    f = new JFrame("Notification List ");
    f.setLocationRelativeTo(parent);
    cNode = currentNode;

    MOCNode tempmoc = icsModel.getMOCNode();

    dynnoti = null;
    defnoti = null;

    int index = defvmoc.indexOf(tempmoc);
    if (index != -1) {
       defmocnode = (MOCNode) defvmoc.get(index);
       defnoti = defmocnode.getNotification();   
	    for (int i = 0; i < defnoti.size(); i++) {
	       notifications.addSourceElements(new String[] {((DIMMOC) defnoti.get(i)).getNotificationName()});
	    } 
    }

    int mocIdNumber = tempmoc.getMocIdNumber();    
    index = dynvmoc.indexOf(tempmoc);
    MOCNode dynmocnode = (MOCNode) dynvmoc.get(index);
    int tempmocIdNumber = dynmocnode.getMocIdNumber();

    while (tempmocIdNumber != mocIdNumber) {
       index = dynvmoc.indexOf(tempmoc,index+1);
       dynmocnode = (MOCNode) dynvmoc.get(index);
       tempmocIdNumber = dynmocnode.getMocIdNumber();
    }   
    dynnoti = dynmocnode.getNotification();
 
    selectedDyn = new String[dynnoti.size()];
    for (int i = 0; i < dynnoti.size(); i++) {
       notifications.addDestinationElements(new String[] {((DIMMOC) dynnoti.get(i)).getNotificationName()});
       if(((DIMMOC) dynnoti.get(i)).isPrivate)
    	   ((MyListRenderer)destList.getCellRenderer()).addPrivate(((DIMMOC) dynnoti.get(i)).notification_name);
       selectedDyn[i] = ((DIMMOC) dynnoti.get(i)).getNotificationName();
       sourceListModel.removeElement(selectedDyn[i]);    
    }

    sourceList.getSelectionModel().clearSelection();

    f.getContentPane().add(notifications, BorderLayout.CENTER);
    f.setSize(400, 300);
    f.setVisible(true);
}

  public String getSourceChoicesTitle() {
    return sourceLabel.getText();
  }

  public void setSourceChoicesTitle(String newValue) {
    sourceLabel.setText(newValue);
  }

  public String getDestinationChoicesTitle() {
    return destLabel.getText();
  }

  public void setDestinationChoicesTitle(String newValue) {
    destLabel.setText(newValue);
  }

  public void clearSourceListModel() {
    sourceListModel.clear();
  }

  public void clearDestinationListModel() {
    destListModel.clear();
  }

  public void addSourceElements(ListModel newValue) {
    fillListModel(sourceListModel, newValue);
  }

  public void setSourceElements(ListModel newValue) {
    clearSourceListModel();
    addSourceElements(newValue);
  }

  public void addDestinationElements(ListModel newValue) {
    fillListModel(destListModel, newValue);
  }

  private void fillListModel(SortedListModel model, ListModel newValues) {
    int size = newValues.getSize();
    for (int i = 0; i < size; i++) {
      model.add(newValues.getElementAt(i));
    }
  }

  public void addSourceElements(Object newValue[]) {
    fillListModel(sourceListModel, newValue);
  }

  public void setSourceElements(Object newValue[]) {
    clearSourceListModel();
    addSourceElements(newValue);
  }

  public void addDestinationElements(Object newValue[]) {
    fillListModel(destListModel, newValue);
  }

  private void fillListModel(SortedListModel model, Object newValues[]) {  
    model.addAll(newValues);
  }

  public Iterator sourceIterator() {
    return sourceListModel.iterator();
  }

  public Iterator destinationIterator() {
    return destListModel.iterator();
  }

  public void setSourceCellRenderer(ListCellRenderer newValue) {
    sourceList.setCellRenderer(newValue);
  }

  public ListCellRenderer getSourceCellRenderer() {
    return sourceList.getCellRenderer();
  }

  public void setDestinationCellRenderer(ListCellRenderer newValue) {
    destList.setCellRenderer(newValue);
  }

  public ListCellRenderer getDestinationCellRenderer() {
    return destList.getCellRenderer();
  }

  public void setVisibleRowCount(int newValue) {
    sourceList.setVisibleRowCount(newValue);
    destList.setVisibleRowCount(newValue);
  }

  public int getVisibleRowCount() {
    return sourceList.getVisibleRowCount();
  }

  public void setSelectionBackground(Color newValue) {
    sourceList.setSelectionBackground(newValue);
    destList.setSelectionBackground(newValue);
  }

  public Color getSelectionBackground() {
    return sourceList.getSelectionBackground();
  }

  public void setSelectionForeground(Color newValue) {
    sourceList.setSelectionForeground(newValue);
    destList.setSelectionForeground(newValue);
  }

  public Color getSelectionForeground() {
    return sourceList.getSelectionForeground();
  }

  private void clearSourceSelected() {
    Object selected[] = sourceList.getSelectedValues();
    for (int i = selected.length - 1; i >= 0; --i) {
      sourceListModel.removeElement(selected[i]);
    }
    sourceList.getSelectionModel().clearSelection();
  }

  private void clearDestinationSelected() {
    Object selected[] = destList.getSelectedValues();
    for (int i = selected.length - 1; i >= 0; --i) {
      destListModel.removeElement(selected[i]);
    }
    destList.getSelectionModel().clearSelection();
  }

  private void init() {

    setLayout(new GridBagLayout());
    
    JPanel p0 = new JPanel();
    MyListRenderer listRenderer = new MyListRenderer();
    
    p0.setLayout(new GridBagLayout());
    
    sourceLabel = new JLabel(DEFAULT_SOURCE_CHOICE_LABEL);
    sourceListModel = new SortedListModel();
    sourceList = new JList(sourceListModel);
    sourceList.setCellRenderer(listRenderer);
    
    p0.add(sourceLabel, new GridBagConstraints(0, 0, 1, 1, 0, 0,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    p0.add(new JScrollPane(sourceList), new GridBagConstraints(0, 1, 1, 5, .5,
        1, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
        EMPTY_INSETS, 0, 0));

    addButton = new JButton(ADD_BUTTON_LABEL);
    p0.add(addButton, new GridBagConstraints(1, 2, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    addButton.addActionListener(this);
    removeButton = new JButton(REMOVE_BUTTON_LABEL);
    p0.add(removeButton, new GridBagConstraints(1, 4, 1, 2, 0, .25,
        GridBagConstraints.CENTER, GridBagConstraints.NONE, new Insets(
            0, 5, 0, 5), 0, 0));
    removeButton.addActionListener(this);

    destLabel = new JLabel(DEFAULT_DEST_CHOICE_LABEL);
    destListModel = new SortedListModel();
    destList = new JList(destListModel);
       
    destList.setCellRenderer(listRenderer);
    
    p0.add(destLabel, new GridBagConstraints(2, 0, 1, 1, 0, 0,
        GridBagConstraints.CENTER, GridBagConstraints.NONE,
        EMPTY_INSETS, 0, 0));
    p0.add(new JScrollPane(destList), new GridBagConstraints(2, 1, 1, 5, .5,
        1.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
        EMPTY_INSETS, 0, 0));
    
    add(p0, new GridBagConstraints(0,0,GridBagConstraints.REMAINDER, 1,
    		0,1,GridBagConstraints.NORTHEAST, GridBagConstraints.BOTH, new Insets(5,5,5,5),0,0));
    
    JPanel p1 = new JPanel();
    p1.setLayout(new GridBagLayout());
    btnAddChanges = new JButton("Add changes");
    btnAddPrivate = new JButton("<html>Add Private Notification...</html>");
    btnAddPrivate.setForeground(Color.red);
    btnClose = new JButton("Close");
    btnAddChanges.addActionListener(this);
    btnAddPrivate.addActionListener(this);
    btnClose.addActionListener(this);
    btnAddChanges.setBackground(new Color(204, 204, 255));
    btnAddPrivate.setBackground(new Color(204, 204, 255));
    btnClose.setBackground(new Color(204, 204, 255));
    p1.add(btnAddChanges, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.WEST,
    		GridBagConstraints.NONE, new Insets(5,5,5,5),0,0));
    p1.add(btnAddPrivate, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.CENTER,
    		GridBagConstraints.NONE, new Insets(5,5,5,5),0,0));
    p1.add(btnClose, new GridBagConstraints(0,0,1,1,1,1,GridBagConstraints.EAST,
    		GridBagConstraints.NONE, new Insets(5,5,5,5),0,0));
    p1.setBorder(BorderFactory.createEtchedBorder());
    add(p1, new GridBagConstraints(GridBagConstraints.RELATIVE,GridBagConstraints.RELATIVE,1,1,1,0,GridBagConstraints.NORTHWEST,
    		GridBagConstraints.BOTH, new Insets(5,5,5,5),0,0)); 

   }
 
  public void processUpdate() {

     String dynstring;
     String selectedString;

     int compareint;

     int dynlen = dynnoti.size();

     String[] notiSelected = new String[destListModel.getSize() - vectPrivate.size()];
  
     int k = 0;
     for (int i = 0; i < destListModel.getSize(); i++) {
    	 boolean isPrivate = false;
        
        for(int j = 0; j < vectPrivate.size(); j++)
        {
        	NotificationNode n = (NotificationNode)vectPrivate.get(j);
        	if(n.notification_name.equals((String) destListModel.getElementAt(i)))
        	{
        		isPrivate = true;
        		j = vectPrivate.size();
        	}
        }
        if(!isPrivate){
        	notiSelected[k] = (String) destListModel.getElementAt(i);
        	k++;
        }
     }

     int selectedlen = notiSelected.length;
    
     int dyncnt = 0;
     int selectedcnt = 0;

     String[] dynnotiArray = new String[dynnoti.size()];
     
     for (int i = 0;i < dynnoti.size();i++) {
         dynnotiArray[i] = dynnoti.get(i).toString();
     }
     if(dynnotiArray != null)
    	 Arrays.sort(dynnotiArray);
     if(notiSelected != null)
    	 Arrays.sort(notiSelected);

     MOCNode mocNode = icsModel.getMOCNode();

     int mocIdNumber = mocNode.getMocIdNumber();
     int inx = icsModel.getcurVMoc().indexOf(mocNode);    		     
     MOCNode vmocNode = (MOCNode)icsModel.getcurVMoc().get(inx);
     int tempmocIdNumber = vmocNode.getMocIdNumber();

     while (tempmocIdNumber != mocIdNumber) {
        inx = icsModel.getcurVMoc().indexOf(mocNode,inx+1);
        vmocNode = (MOCNode)icsModel.getcurVMoc().get(inx);
        tempmocIdNumber = vmocNode.getMocIdNumber();
     }    
     while (dyncnt < dynlen && selectedcnt < selectedlen) {
        dynstring = dynnotiArray[dyncnt];
        selectedString = notiSelected[selectedcnt];
        compareint = dynstring.compareTo(selectedString);

        if (compareint < 0) {
           dyncnt = dyncnt + 1;             
           deleteVector(vmocNode,dynstring);
        }
        else if (compareint > 0) {
           // add vector
           addVector(vmocNode,selectedString);
           selectedcnt = selectedcnt +1;      
        }
        else {
           dyncnt = dyncnt + 1;
           selectedcnt = selectedcnt + 1;
        }
     }
     if (dyncnt < dynlen) {
        for (int i = dyncnt; i < dynlen; i++) {
           dynstring = dynnotiArray[dyncnt];
           deleteVector(vmocNode,dynstring);
        }
     }
     else if (selectedcnt < selectedlen) {
        for (int i = selectedcnt; i < selectedlen; i++) {
           selectedString = notiSelected[selectedcnt];
           addVector(vmocNode,selectedString);
           selectedcnt = selectedcnt + 1;
        }
     }
     
     for(int i = 0; i < vectPrivate.size(); i++){
    	 NotificationNode n = (NotificationNode)vectPrivate.get(i);
    	 vmocNode.addNotification(n);
     }
     icsModel.fireEvent(new MVCArg("node",vmocNode));
  }

  public void addVector(MOCNode mnode, String vecToBeAdded) {

     Vector vmocDef = icsModel.getVMoc();
     
     MOCNode tempmoc = icsModel.getMOCNode();

     int index = vmocDef.indexOf(tempmoc);

     MOCNode mocNode = (MOCNode) vmocDef.get(index);
     Vector mocNoti = mocNode.getNotification();


     int DeleteFlag = 0;
   
     while (DeleteFlag == 0  && mocNoti.size() != 0) {      
        for (int i = 0; i < mocNoti.size(); i++) {
           if (vecToBeAdded.equals(((DIMMOC) mocNoti.get(i)).getNotificationName())) {
              NotificationNode newNoti = new NotificationNode();
              newNoti.setNotificationName(((NotificationNode) mocNoti.get(i)).getNotificationName());
              newNoti.setNotificationId(((NotificationNode) mocNoti.get(i)).getNotificationId());
              newNoti.setNotificationKeyNumber(((NotificationNode) mocNoti.get(i)).getNotificationKeyNumber());
              newNoti.setNotificationEventParameter(((NotificationNode) mocNoti.get(i)).getNotificationEventParameter());
              newNoti.setNotificationTermCode(((NotificationNode) mocNoti.get(i)).getNotificationTermCode());
              newNoti.setNotificationReference(((NotificationNode) mocNoti.get(i)).getNotificationReference());
              newNoti.setNotificationQual(((NotificationNode) mocNoti.get(i)).getNotificationQual());
              newNoti.setNotificationRestrictions(((NotificationNode) mocNoti.get(i)).getNotificationRestrictions());
              newNoti.setNotificationComment(((NotificationNode) mocNoti.get(i)).getNotificationComment());               
              mnode.addNotification(newNoti);
              DeleteFlag = 1;
           } 
        }
     }
  }

  public void deleteVector(MOCNode mnode, String vecToBeDeleted) {

     Vector vNode;
     vNode = mnode.getNotification();

     int DeleteFlag = 0;
   
     while (DeleteFlag == 0  && vNode.size() != 0) {      
        for (int i = 0; i < vNode.size(); i++) {
           if (vecToBeDeleted.equals(((DIMMOC) vNode.get(i)).getNotificationName())) {
              vNode.remove(i);
              DeleteFlag = 1;
           } 
        }
     }
  }

  public void actionPerformed(ActionEvent arg0) {
     if(arg0.getSource() == btnAddChanges) {
        // save changes
        processUpdate();
        f.dispose();
     }
     else if(arg0.getSource() == btnClose) {
	// exit
        f.dispose();
        icsModel = null;
     }
     else if(arg0.getSource() == removeButton)
     {
    	 Object selected[] = destList.getSelectedValues();
         int [] indices = destList.getSelectedIndices();
         int indices_cnt = 0;
         int Vector_Match_Flag = 0;
         String notificationNames = null;
         int numOfNotifications = 0;
         Vector vnoti = defnoti;
         for (int i = 0; i < selected.length; i++) {
//        	we look for private attributes to delete
           	for(int p = 0; p < vectPrivate.size(); p++){
           		if(selected[i].toString().equals(((DIMMOC) vectPrivate.get(p)).getNotificationName())){
           			vectPrivate.remove(p);
           			p = vectPrivate.size();
           		}
           	}
           	
            int Select_Match_Flag = 0; 
            if(vnoti != null){
	            for (int x = 0; x < vnoti.size(); x++) {
	               if (selected[i].toString().equals(((DIMMOC) vnoti.get(x)).getNotificationName())) {
	                  destList.removeSelectionInterval(indices[indices_cnt],indices[indices_cnt]);
	                  indices_cnt = indices_cnt + 1;
	                  if (Vector_Match_Flag == 0) {
	                     notificationNames = selected[i].toString();
	                     numOfNotifications = numOfNotifications + 1;
	                  }
	                  else {
	                     notificationNames = notificationNames+", "+selected[i].toString();
	                     numOfNotifications = numOfNotifications + 1;
	                  }
	                  Vector_Match_Flag = 1;
	                  Select_Match_Flag = 1;
	               }
	            }
	            if (Select_Match_Flag == 0) {
	               indices_cnt = indices_cnt + 1;
	            }
	         }
         }
         if (Vector_Match_Flag != 0) {
           selected = destList.getSelectedValues();
           String msg = null;
           if (numOfNotifications == 1 ) {
              msg = "The Notification "+notificationNames+" CANNOT BE REMOVED since it is a DEFAULT NOTIFICATION";
           }
           else {
              msg = "The Notifications "+notificationNames+" CANNOT BE REMOVED since they are DEFAULT NOTIFICATIONS";
           }
           String title = "NOTIFICATION WARNING MESSAGE";
           JOptionPane.showConfirmDialog(this, msg, title,JOptionPane.DEFAULT_OPTION,JOptionPane.WARNING_MESSAGE);
         } 
         selected = destList.getSelectedValues();
         addSourceElements(selected);
         clearDestinationSelected();
     }
     else if(arg0.getSource() == addButton)
     {
    	 Object selected[] = sourceList.getSelectedValues();
         addDestinationElements(selected);
         clearSourceSelected();
     }
     else if(arg0.getSource() == btnAddPrivate)
     {
    	 JFrame f = new JFrame("Add private notification");
    	 
    	 
    	 String[] labels = new String[3];
    	 labels[0] = "Notification ID:";
    	 labels[1] = "Notification Name:";
    	 labels[2] = "Term Code:";
    	 AddPrivateDialog dialog = new AddPrivateDialog(this, f,labels, AddPrivateDialog.privateNoti);
    	 dialog.setLocationRelativeTo(this);
    	 dialog.pack();
    	 dialog.setICSModel(icsModel);
    
    	 dialog.setVisible(true);
     }
  }

public void update(Observable o, Object arg) {
	if(o instanceof ICSModel) {
		if(("private/"+AddPrivateDialog.privateNoti).equals(((MVCArg)arg).getName()) && icsModel != null) {
			String[] result = (String[]) ((MVCArg)arg).getOValue();
			NotificationNode n = new NotificationNode();
			n.notification_name = result[1];
			n.notification_id = result[0];
			n.noti_termcode = result[2];
			n.isPrivate = true;
			vectPrivate.add(n);
			destListModel.add(n.notification_name);
			MyListRenderer renderer = (MyListRenderer) destList.getCellRenderer();
			renderer.addPrivate(n.notification_name);
		}	
	}	
}
}
