package com.quantum.view.bookmark;


import java.beans.PropertyChangeEvent;
import java.beans.PropertyChangeListener;
import java.util.Vector;

import org.eclipse.jface.action.Action;
import org.eclipse.jface.action.IAction;
import org.eclipse.jface.action.IMenuListener;
import org.eclipse.jface.action.IMenuManager;
import org.eclipse.jface.action.MenuManager;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.viewers.IOpenListener;
import org.eclipse.jface.viewers.ISelectionProvider;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.OpenEvent;
import org.eclipse.jface.viewers.StructuredSelection;
import org.eclipse.jface.viewers.TreeViewer;
import org.eclipse.swt.SWT;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IActionBars;
import org.eclipse.ui.WorkbenchException;
import org.eclipse.ui.actions.ActionContext;
import org.eclipse.ui.part.ViewPart;

import com.quantum.ImageStore;
import com.quantum.Messages;
import com.quantum.QuantumPlugin;
import com.quantum.actions.CustomCopyAction;
import com.quantum.extensions.ExtensionAction;
import com.quantum.extensions.ProcessServiceMembers;

public class BookmarkView extends ViewPart implements PropertyChangeListener {
	private CustomCopyAction customCopyAction1;
	private CustomCopyAction customCopyAction2;
	private CustomCopyAction customCopyAction3;
	private Vector extensionVector;
    
    private BookmarkViewActionGroup actionGroup;

	private TreeViewer treeViewer;
    private BookmarkLabelProvider labelProvider = new BookmarkLabelProvider();
    
	/**
	 * @return	-
	 * 	The instance of the BookmarkView. There is no guarantee of it being a singleton
	 * 	due to the workspace creating a new one (does the workspace call getInstance() ? ).
	 * 	It seems to work.
	 */
	public synchronized static BookmarkView getInstance() {
		return (BookmarkView) QuantumPlugin.getDefault().getView("com.quantum.view.bookmarkview");
	}
	/**
	 * Returns the current selected object in the tree. If it's a multiple selection, return the first.
	 * @return
	 */
	public Object getCurrent() {
		if (treeViewer == null) return null;
		return ((StructuredSelection) treeViewer.getSelection())
					.getFirstElement();
	}
	/**
	 * Returns the current selected objects in the tree, in the form of a StructuredSelection.
	 * @return
	 */
	public StructuredSelection getSelection() {
		if (treeViewer == null) return null;
		return ((StructuredSelection) treeViewer.getSelection());
	}
	
	/** 
	 * Navigates the tree to get the current bookmark (root) of the selected element.
	 * If it's a multiple selection, it takes the first one.
	 * @return
	 */
	public BookmarkNode getCurrentBookmark() {
		TreeNode current = (TreeNode) getCurrent();
		return getRoot(current);
	}

	private static BookmarkNode getRoot(TreeNode node){
		if (node == null) return null;
		while (!( node instanceof BookmarkNode))
		{
			node = node.getParent();
		}
		if (node instanceof BookmarkNode) return (BookmarkNode) node;
		else return null;

	}
	public void refresh() {
		treeViewer.refresh();
	}
	public void createPartControl(org.eclipse.swt.widgets.Composite parent) {

		treeViewer = new TreeViewer(
            parent, SWT.MULTI | SWT.H_SCROLL | SWT.V_SCROLL);
		treeViewer.setContentProvider(new BookmarkContentProvider(this));
		treeViewer.setLabelProvider(this.labelProvider);
        BookmarkListNode input = BookmarkListNode.getInstance();
		treeViewer.setInput(input);
        initActions();
        
        input.addPropertyChangeListener(this);
        
        initializePopUpMenu();
        fillActionBars();
        
		treeViewer.addOpenListener(new IOpenListener() {
			public void open(OpenEvent event) {
                ActionContext context = new ActionContext(
                    getSelection());
                BookmarkView.this.actionGroup.setContext(context);
                IAction action = actionGroup.getOpenAction();
                if (action != null) {
                    action.run();
                }
			}
		});
		
	}
    private void fillActionBars() {
        Action enableTableSizes = new Action() {
        	public void run() {
        		labelProvider.getLabelDecorationInstructions().setSizeVisible(isChecked());
                treeViewer.refresh();
        	}
        };
        enableTableSizes.setText(Messages.getString("BookmarkView.ShowTableSizes")); //$NON-NLS-1$
        enableTableSizes.setChecked(false);

        IActionBars actionBars = getViewSite().getActionBars();
        actionBars.getMenuManager().add(enableTableSizes);
        
        Action showDatabaseData = new Action() {
            public void run() {
                labelProvider.getLabelDecorationInstructions().setDatabaseDataVisible(isChecked());
                treeViewer.refresh();
            }
        };
        showDatabaseData.setText(Messages.getString("BookmarkView.ShowDatabaseData")); //$NON-NLS-1$
        showDatabaseData.setChecked(false);
        actionBars.getMenuManager().add(showDatabaseData);

        this.actionGroup.fillActionBars(actionBars);
    }
    
    private void initializePopUpMenu() {
        MenuManager manager = new MenuManager();
        manager.setRemoveAllWhenShown(true);
        manager.addMenuListener(new IMenuListener() {
            public void menuAboutToShow(IMenuManager mgr) {
                fillContextMenu(mgr);
            }
        });
        Menu fTextContextMenu =
            manager.createContextMenu(treeViewer.getControl());
        treeViewer.getControl().setMenu(fTextContextMenu);
        // register the menu to the site so that we can allow 
        // actions to be plugged in
        getSite().registerContextMenu(manager, this.treeViewer);
    }
	public void initActions() {
        
        this.actionGroup = new BookmarkViewActionGroup(this, this.treeViewer);
        

		extensionVector = new Vector();
		try {
			ProcessServiceMembers.process(this, extensionVector);
		} catch (WorkbenchException e) {
			e.printStackTrace();
		}

	}
	
	/**
	 * 
	 */
	private void initCustomCopyActions() {
		IPreferenceStore store = QuantumPlugin.getDefault().getPreferenceStore();
        String text1 = store.getString("customCopyName1");
        if (text1 != null && text1.trim().length() > 0) {
			this.customCopyAction1 = new CustomCopyAction(1); // 1 is unused, just in case more custom copies are defined        
			this.customCopyAction1.setText(text1); //$NON-NLS-1$
			this.customCopyAction1.setImageDescriptor(
					ImageStore.getImageDescriptor(ImageStore.COPY)); //$NON-NLS-1$
        }
        String text2 = store.getString("customCopyName2");
        if (text2 != null && text1.trim().length() > 0) {
			this.customCopyAction2 = new CustomCopyAction(2); // 1 is unused, just in case more custom copies are defined        
			this.customCopyAction2.setText(text2); //$NON-NLS-1$
			this.customCopyAction2.setImageDescriptor(
					ImageStore.getImageDescriptor(ImageStore.COPY)); //$NON-NLS-1$
        }
        String text3 = store.getString("customCopyName3");
        if (text3 != null && text1.trim().length() > 0) {
			this.customCopyAction3 = new CustomCopyAction(3); // 1 is unused, just in case more custom copies are defined        
			this.customCopyAction3.setText(text3); //$NON-NLS-1$
			this.customCopyAction3.setImageDescriptor(
					ImageStore.getImageDescriptor(ImageStore.COPY)); //$NON-NLS-1$
        }
	}
	public void dispose(){
		super.dispose();
        BookmarkListNode.getInstance().removePropertyChangeListener(this);
	}

	public Shell getShell() {
		return getSite().getShell();
	}

    /**
     * @see java.beans.PropertyChangeListener#propertyChange(java.beans.PropertyChangeEvent)
     */
    public void propertyChange(PropertyChangeEvent event) {
        if ("bookmarks".equals(event.getPropertyName())) {
            refresh();
        } else if ("name".equals(event.getPropertyName()) && 
            event.getSource() instanceof BookmarkNode) {
            refresh();
        } else if ("connected".equals(event.getPropertyName())) {
            treeViewer.refresh(event.getSource());
            if (Boolean.TRUE.equals(event.getNewValue())) {
                treeViewer.setExpandedState(event.getSource(), true);
            }
        } else {
            treeViewer.refresh(event.getSource());
        }
    }
    
    private void fillContextMenu(IMenuManager mgr) {
    // TODO: this method is pretty barfy... make it cleaner
    
		initCustomCopyActions();
        IStructuredSelection selection = getSelection();
        ActionContext context = new ActionContext(selection);
        this.actionGroup.setContext(context);
        this.actionGroup.fillContextMenu(mgr);
        
        Object sel = getCurrent();
        // If selection is a BookmarkNode
        if (sel instanceof EntityNode) {
            EntityNode entityNode = (EntityNode) sel;
            if (!entityNode.isSequence()) {
            	if (this.customCopyAction1 != null 
            			|| this.customCopyAction2 != null 
						|| this.customCopyAction3 != null) {
	                mgr.add(new Separator());
	                MenuManager subMenu = new MenuManager(Messages.getString("bookmarkview.customCopyAction")); 
	                if (this.customCopyAction1 != null) {
	                    customCopyAction1.selectionChanged(selection);
	                	subMenu.add(customCopyAction1);
	                }
	                if (this.customCopyAction2 != null) {
	                	customCopyAction2.selectionChanged(selection);
	                	subMenu.add(customCopyAction2);
	                }
	                if (this.customCopyAction3 != null) {
	                	customCopyAction3.selectionChanged(selection);
	                	subMenu.add(customCopyAction3);
	                }
	                mgr.add(subMenu);
            	}

				MenuManager subMenuExtension = new MenuManager("Extensions"); 
				for (int i = 0; i < extensionVector.size(); i++) {
					ExtensionAction extensionAction = (ExtensionAction) extensionVector.get(i);
					subMenuExtension.add(extensionAction);
				}
				if (extensionVector.size() > 0) mgr.add(subMenuExtension);
            }
        } else if ((sel instanceof ColumnNode) && (this.customCopyAction1 != null 
        			|| this.customCopyAction2 != null 
					|| this.customCopyAction3 != null)) {
            MenuManager subMenu = new MenuManager(Messages.getString("bookmarkview.customCopyAction")); 
            if (this.customCopyAction1 != null) {
            	customCopyAction1.selectionChanged(selection);
            	subMenu.add(customCopyAction1);
            }
            if (this.customCopyAction2 != null) {
            	customCopyAction2.selectionChanged(selection);
            	subMenu.add(customCopyAction2);
            }
            if (this.customCopyAction3 != null) {
            	customCopyAction3.selectionChanged(selection);
            	subMenu.add(customCopyAction3);
            }
            mgr.add(subMenu);
        }
    }
    /**
     * @see org.eclipse.ui.part.WorkbenchPart#setFocus()
     */
    public void setFocus() {
    }
    

}