/*******************************************************************************
 * Copyright (c) 2003, 2008 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 * IBM Corporation - initial API and implementation
 * Kaloyan Raev, kaloyan.raev@sap.com
 *******************************************************************************/
package org.eclipse.jst.servlet.ui.internal.wizard;

import static org.eclipse.jst.j2ee.web.IServletConstants.QUALIFIED_SERVLET;
import static org.eclipse.jst.servlet.ui.internal.wizard.IWebWizardConstants.DEFAULT_PACKAGE;

import java.util.ArrayList;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.runtime.Status;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.ui.ISharedImages;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableContext;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jst.j2ee.internal.dialogs.FilteredFileSelectionDialog;
import org.eclipse.jst.j2ee.internal.dialogs.TwoArrayQuickSorter;
import org.eclipse.jst.j2ee.internal.dialogs.TypedFileViewerFilter;
import org.eclipse.jst.j2ee.internal.web.providers.WebAppEditResourceHandler;
import org.eclipse.jst.servlet.ui.internal.plugin.ServletUIPlugin;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Table;
import org.eclipse.swt.widgets.TableItem;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.ElementTreeSelectionDialog;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;
import org.eclipse.ui.model.WorkbenchContentProvider;
import org.eclipse.ui.part.PageBook;

/**
 * Insert the type's description here.
 * Creation date: (7/30/2001 11:16:36 AM)
 */
public class MultiSelectFilteredFileSelectionDialog extends
		FilteredFileSelectionDialog implements SelectionListener {
	

	private static class PackageRenderer extends LabelProvider {
		private final Image PACKAGE_ICON = JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_PACKAGE); 

		@Override
		public String getText(Object element) {
			IType type = (IType) element;
			String p = type.getPackageFragment().getElementName();
			if ("".equals(p)) //$NON-NLS-1$
				p = DEFAULT_PACKAGE;
			return (p + " - " + type.getPackageFragment().getParent().getPath().toString()); //$NON-NLS-1$
		}
		@Override
		public Image getImage(Object element) {
			return PACKAGE_ICON;
		}
	}

	private static class TypeRenderer extends LabelProvider {
		private final Image CLASS_ICON = JavaUI.getSharedImages().getImage(ISharedImages.IMG_OBJS_CLASS); 

		@Override
		public String getText(Object element) {
			IType e = ((IType) element);
			return e.getElementName();
		}

		@Override
		public Image getImage(Object element) {
			return CLASS_ICON;
		}

	}
	public final static int JSP = 0;
	public final static int SERVLET = 1;
	protected Button fServletButton;
	protected Button fJSPButton;
	protected int fSelection = -1;
	protected PageBook fPageBook = null;
	protected Control fJspControl = null;
	protected Control fServletControl = null;
	protected Composite fChild = null;
	// construction parameters
	protected IRunnableContext fRunnableContext;
	protected ILabelProvider fElementRenderer;
	protected ILabelProvider fQualifierRenderer;
	private Object[] fElements;
	private boolean fIgnoreCase = true;
	private String fUpperListLabel;
	private String fLowerListLabel;
	// SWT widgets
	private Table fUpperList;
	private Table fLowerList;
	protected Text fText;
	private IType[] fIT;
	private String[] fRenderedStrings;
	private int[] fElementMap;
	private Integer[] fQualifierMap;
	private Object fInput;

	private ISelectionStatusValidator fLocalValidator = null;
	/**
	 * MultiSelectFilteredFileSelectionDialog constructor comment.
	 * @param parent Shell
	 * @param title String
	 * @param message String
	 * @parent extensions String[]
	 * @param allowMultiple boolean
	 */
	public MultiSelectFilteredFileSelectionDialog(Shell parent, String title, String message, String[] extensions, boolean allowMultiple, IProject project) {
		super(parent, title, message, extensions, allowMultiple);
		setShellStyle(SWT.DIALOG_TRIM | SWT.APPLICATION_MODAL | SWT.RESIZE);

		if (title == null)
			setTitle(WebAppEditResourceHandler.getString("File_Selection_UI_")); //$NON-NLS-1$
		if (message == null)
		{
			setMessage(WebAppEditResourceHandler.getString("Select_a_file__UI_")); //$NON-NLS-1$
		}
		fLocalValidator = new SimpleTypedElementSelectionValidator(new Class[] { IFile.class }, allowMultiple);
		setValidator(fLocalValidator);
		
		//StatusInfo currStatus = new StatusInfo();
		//currStatus.setOK();
		Status currStatus = new Status(Status.OK, ServletUIPlugin.PLUGIN_ID, Status.OK, "", null);//$NON-NLS-1$
		
		updateStatus(currStatus);
		fElementRenderer = new TypeRenderer();
		fQualifierRenderer = new PackageRenderer();
		fRunnableContext = ServletUIPlugin.getDefault().getWorkbench().getActiveWorkbenchWindow();
		try {
			IJavaElement jelem = null;
			IProject proj = null;
			jelem = (IJavaElement) project.getAdapter(IJavaElement.class);
			if (jelem == null) {
				IResource resource = (IResource) project.getAdapter(IResource.class);
				if (resource != null) {
					proj = resource.getProject();
					if (proj != null) {
						jelem = org.eclipse.jdt.core.JavaCore.create(proj);
					}
				}
			}
			if(jelem != null){
				IJavaProject jp = jelem.getJavaProject();
	
				IType servletType = jp.findType(QUALIFIED_SERVLET);
				ArrayList servletClasses = new ArrayList();
				if (servletType != null)
				{
					ITypeHierarchy tH = servletType.newTypeHierarchy(jp, null);
					IType[] types = tH.getAllSubtypes(servletType);
					for (int i = 0; i < types.length; i++) {
						if (types[i].isClass() && !servletClasses.contains(types[i]))
							servletClasses.add(types[i]);
					}
				}
				fIT = (IType[]) servletClasses.toArray(new IType[servletClasses.size()]);
				servletClasses = null;
			}
		} catch (Exception e) {
			ServletUIPlugin.log(e);
		}
	}
	
	/**
	 * @private
	 */
	@Override
	protected void computeResult() {
		if (fSelection == JSP) {
			super.computeResult();
		} else {
			IType type = (IType) getWidgetSelection();
			if (type != null) {
				java.util.List result = new ArrayList(1);
				result.add(type);
				setResult(result);
			}
		}
	}
	
	@Override
	public void create() {
		super.create();
		fText.setFocus();
		rematch(""); //$NON-NLS-1$
		updateOkState();
	}
	
	/**
	 * Creates and returns the contents of this dialog's 
	 * button bar.
	 * <p>
	 * The <code>Dialog</code> implementation of this framework method
	 * lays out a button bar and calls the <code>createButtonsForButtonBar</code>
	 * framework method to populate it. Subclasses may override.
	 * </p>
	 *
	 * @param parent the parent composite to contain the button bar
	 * @return the button bar control
	 */
	@Override
	protected Control createButtonBar(Composite parent) {

		Composite composite = new Composite(parent, SWT.NULL);
		GridLayout layout = new GridLayout();

		layout.numColumns = 2;

		layout.marginHeight = 0;
		layout.marginWidth = 0;
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_HORIZONTAL));

		Composite composite2 = new Composite(composite, SWT.NONE);

		// create a layout with spacing and margins appropriate for the font size.
		layout = new GridLayout();
		layout.numColumns = 0; // this is incremented by createButton
		layout.makeColumnsEqualWidth = true;
		layout.marginWidth = convertHorizontalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.HORIZONTAL_MARGIN);
		layout.marginHeight = convertVerticalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.VERTICAL_MARGIN);
		layout.horizontalSpacing = convertHorizontalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.HORIZONTAL_SPACING);
		layout.verticalSpacing = convertVerticalDLUsToPixels(org.eclipse.jface.dialogs.IDialogConstants.VERTICAL_SPACING);

		composite2.setLayout(layout);

		GridData data = new GridData(GridData.HORIZONTAL_ALIGN_END | GridData.VERTICAL_ALIGN_CENTER);
		composite2.setLayoutData(data);

		composite2.setFont(parent.getFont());

		// Add the buttons to the button bar.
		super.createButtonsForButtonBar(composite2);

		return composite;
	}
	
	/*
	 * @private
	 */
	@Override
	protected Control createDialogArea(Composite parent) {
		GridData gd = new GridData();

		fChild = new Composite(parent, SWT.NONE);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(fChild, "com.ibm.etools.webapplicationedit.webx2010"); //$NON-NLS-1$
		GridLayout gl = new GridLayout();
		gl.numColumns = 2;
		gl.marginHeight = 0;
		fChild.setLayout(gl);

		gd.verticalAlignment = GridData.FILL;
		gd.grabExcessVerticalSpace = true;
		fChild.setLayoutData(gd);

		// Create the Web Type radio buttons and text fields.
		fServletButton = new Button(fChild, SWT.RADIO);
		fServletButton.setText(WebAppEditResourceHandler.getString("Servlet_UI_")); //$NON-NLS-1$ = Servlet
		gd = new GridData();
		fServletButton.setLayoutData(gd);
		fServletButton.addSelectionListener(this);

		fJSPButton = new Button(fChild, SWT.RADIO);
		fJSPButton.setText(WebAppEditResourceHandler.getString("JSP_UI_")); //$NON-NLS-1$ = JSP
		gd = new GridData();
		fJSPButton.setLayoutData(gd);
		fJSPButton.addSelectionListener(this);

		if (fSelection == JSP)
			fJSPButton.setSelection(true);
		else {
			fServletButton.setSelection(true);
			fSelection = SERVLET;
		}

		fPageBook = new PageBook(fChild, SWT.NONE);
		gd = new GridData();
		gd.horizontalAlignment = GridData.FILL;
		gd.verticalAlignment = GridData.FILL;
		gd.grabExcessHorizontalSpace = true;
		gd.grabExcessVerticalSpace = true;
		gd.horizontalSpan = 2;
		fPageBook.setLayoutData(gd);
		fJspControl = super.createDialogArea(fPageBook);

		Composite composite = new Composite(fPageBook, SWT.NONE);
		GridLayout layout = new GridLayout();
		layout.marginHeight = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_MARGIN);
		layout.marginWidth = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_MARGIN);
		layout.verticalSpacing = convertVerticalDLUsToPixels(IDialogConstants.VERTICAL_SPACING);
		layout.horizontalSpacing = convertHorizontalDLUsToPixels(IDialogConstants.HORIZONTAL_SPACING);
		composite.setLayout(layout);
		composite.setLayoutData(new GridData(GridData.FILL_BOTH));
		composite.setFont(parent.getFont());

		Label messageLabel = new Label(composite, SWT.NONE);
		gd = new GridData();
		messageLabel.setLayoutData(gd);
		messageLabel.setText(WebAppEditResourceHandler.getString("Choose_a_servlet__1")); //$NON-NLS-1$

		fText = createText(composite);

		messageLabel = new Label(composite, SWT.NONE);
		gd = new GridData();
		messageLabel.setLayoutData(gd);
		messageLabel.setText(WebAppEditResourceHandler.getString("Matching_servlets__2")); //$NON-NLS-1$

		fUpperList = createUpperList(composite);

		messageLabel = new Label(composite, SWT.NONE);
		gd = new GridData();
		messageLabel.setLayoutData(gd);
		messageLabel.setText(WebAppEditResourceHandler.getString("Qualifier__3")); //$NON-NLS-1$

		fLowerList = createLowerList(composite);

		fServletControl = composite;

		if (fSelection == JSP)
			fPageBook.showPage(fJspControl);
		else
			fPageBook.showPage(fServletControl);
		return parent;
	}
	
	/**
	 * Creates the list widget and sets layout data.
	 * @return org.eclipse.swt.widgets.List
	 */
	private Table createLowerList(Composite parent) {
		if (fLowerListLabel != null)
			 (new Label(parent, SWT.NONE)).setText(fLowerListLabel);

		Table list = new Table(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
		list.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event evt) {
				handleLowerSelectionChanged();
			}
		});
		list.addListener(SWT.MouseDoubleClick, new Listener() {
			public void handleEvent(Event evt) {
				handleLowerDoubleClick();
			}
		});
		list.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				fQualifierRenderer.dispose();
			}
		});
		GridData spec = new GridData();
		spec.widthHint = convertWidthInCharsToPixels(50);
		spec.heightHint = convertHeightInCharsToPixels(5);
		spec.grabExcessVerticalSpace = true;
		spec.grabExcessHorizontalSpace = true;
		spec.horizontalAlignment = GridData.FILL;
		spec.verticalAlignment = GridData.FILL;
		list.setLayoutData(spec);
		return list;
	}
	
	/**
	 * Creates the text widget and sets layout data.
	 * @return org.eclipse.swt.widgets.Text
	 */
	private Text createText(Composite parent) {
		Text text = new Text(parent, SWT.BORDER);
		GridData spec = new GridData();
		spec.grabExcessVerticalSpace = false;
		spec.grabExcessHorizontalSpace = true;
		spec.horizontalAlignment = GridData.FILL;
		spec.verticalAlignment = GridData.BEGINNING;
		text.setLayoutData(spec);
		Listener l = new Listener() {
			public void handleEvent(Event evt) {
				rematch(fText.getText());
			}
		};
		text.addListener(SWT.Modify, l);
		return text;
	}
	
	/**
	 * Creates the list widget and sets layout data.
	 * @return org.eclipse.swt.widgets.List
	 */
	private Table createUpperList(Composite parent) {
		if (fUpperListLabel != null)
			 (new Label(parent, SWT.NONE)).setText(fUpperListLabel);

		Table list = new Table(parent, SWT.BORDER | SWT.V_SCROLL | SWT.H_SCROLL);
		list.addListener(SWT.Selection, new Listener() {
			public void handleEvent(Event evt) {
				handleUpperSelectionChanged();
			}
		});
		list.addListener(SWT.MouseDoubleClick, new Listener() {
			public void handleEvent(Event evt) {
				handleUpperDoubleClick();
			}
		});
		list.addDisposeListener(new DisposeListener() {
			public void widgetDisposed(DisposeEvent e) {
				fElementRenderer.dispose();
			}
		});
		GridData spec = new GridData();
		spec.widthHint = convertWidthInCharsToPixels(50);
		spec.heightHint = convertHeightInCharsToPixels(15);
		spec.grabExcessVerticalSpace = true;
		spec.grabExcessHorizontalSpace = true;
		spec.horizontalAlignment = GridData.FILL;
		spec.verticalAlignment = GridData.FILL;
		list.setLayoutData(spec);
		return list;
	}
	
	/**
	 * @return the ID of the button that is 'pressed' on doubleClick in the lists.
	 * By default it is the OK button.
	 * Override to change this setting.
	 */
	protected int getDefaultButtonID() {
		return IDialogConstants.OK_ID;
	}
	
	public int getSelectedItem() {
		return fSelection;
	}
	
	protected Object getWidgetSelection() {
		int i = fLowerList.getSelectionIndex();
		if (fQualifierMap != null) {
			if (fQualifierMap.length == 1)
				i = 0;
			if (i < 0) {
				return null;
			} 
			Integer index = fQualifierMap[i];
			return fElements[index.intValue()];
		}
		return null;
	}
	
	protected final void handleLowerDoubleClick() {
		if (getWidgetSelection() != null)
			buttonPressed(getDefaultButtonID());
	}
	
	protected final void handleLowerSelectionChanged() {
		updateOkState();
	}
	
	protected final void handleUpperDoubleClick() {
		if (getWidgetSelection() != null)
			buttonPressed(getDefaultButtonID());
	}
	
	protected final void handleUpperSelectionChanged() {
		int selection = fUpperList.getSelectionIndex();
		if (selection >= 0) {
			int i = fElementMap[selection];
			int k = i;
			int length = fRenderedStrings.length;
			while (k < length && fRenderedStrings[k].equals(fRenderedStrings[i])) {
				k++;
			}
			updateLowerListWidget(i, k);
		} else
			updateLowerListWidget(0, 0);
	}
	
	@Override
	public int open() {

		if (fIT == null || fIT.length == 0) {
			if (!hasJSPs())
			{
				MessageDialog.openInformation(getShell(), WebAppEditResourceHandler.getString("Empty_List_1"), WebAppEditResourceHandler.getString("_INFO_No_servlets_exist_to_add._1"));  //$NON-NLS-2$ //$NON-NLS-1$
				return CANCEL;
			}
			fSelection = JSP;
		}
		setElements(fIT);
		setInitialSelection(""); //$NON-NLS-1$
		return super.open();
	}
	
	/**
	 * update the list to reflect a new match string.
	 * @param matchString java.lang.String
	 */
	protected final void rematch(String matchString) {
		int k = 0;
		String text = fText.getText();
		StringMatcher matcher = new StringMatcher(text + "*", fIgnoreCase, false); //$NON-NLS-1$
		String lastString = null;
		int length = fElements.length;
		for (int i = 0; i < length; i++) {
			while (i < length && fRenderedStrings[i].equals(lastString))
				i++;
			if (i < length) {
				lastString = fRenderedStrings[i];
				if (matcher.match(fRenderedStrings[i])) {
					fElementMap[k] = i;
					k++;
				}
			}
		}
		fElementMap[k] = -1;

		updateUpperListWidget(fElementMap, k);
	}
	
	/**
		 * 
		 * @return java.lang.String[]
		 * @param p org.eclipse.jface.elements.IIndexedProperty
		 */
	private String[] renderStrings(Object[] p) {
		String[] strings = new String[p.length];
		int size = strings.length;
		for (int i = 0; i < size; i++) {
			strings[i] = fElementRenderer.getText(p[i]);
		}
		new TwoArrayQuickSorter(fIgnoreCase).sort(strings, p);
		return strings;
	}

	public void setElements(Object[] elements) {
		fElements = elements;
		fElementMap = new int[fElements.length + 1];
		fRenderedStrings = renderStrings(fElements);
	}

	public void setSelectedItem(int newSelection) {
		fSelection = newSelection;
	}

	private void updateLowerListWidget(int from, int to) {
		fLowerList.removeAll();
		fQualifierMap = new Integer[to - from];
		String[] qualifiers = new String[to - from];
		for (int i = from; i < to; i++) {
			// XXX: 1G65LDG: JFUIF:WIN2000 - ILabelProvider used outside a viewer
			qualifiers[i - from] = fQualifierRenderer.getText(fElements[i]);
			fQualifierMap[i - from] = new Integer(i);
		}

		new TwoArrayQuickSorter(fIgnoreCase).sort(qualifiers, fQualifierMap);

		for (int i = 0; i < to - from; i++) {
			TableItem ti = new TableItem(fLowerList, i);
			ti.setText(qualifiers[i]);
			// XXX: 1G65LDG: JFUIF:WIN2000 - ILabelProvider used outside a viewer
			Image img = fQualifierRenderer.getImage(fElements[from + i]);
			if (img != null)
				ti.setImage(img);
		}

		if (fLowerList.getItemCount() > 0)
			fLowerList.setSelection(0);
		updateOkState();
	}
	
	private void updateOkState() {
		Button okButton = getOkButton();
		if (okButton != null)
			okButton.setEnabled(getWidgetSelection() != null);
	}
	
	private void updateUpperListWidget(int[] indices, int size) {
		fUpperList.setRedraw(false);
		int itemCount = fUpperList.getItemCount();
		if (size < itemCount)
			fUpperList.remove(0, itemCount - size - 1);
		TableItem[] items = fUpperList.getItems();
		for (int i = 0; i < size; i++) {
			TableItem ti = null;
			if (i < itemCount)
				ti = items[i];
			else
				ti = new TableItem(fUpperList, i);
			ti.setText(fRenderedStrings[indices[i]]);
			// XXX: 1G65LDG: JFUIF:WIN2000 - ILabelProvider used outside a viewer
			Image img = fElementRenderer.getImage(fElements[indices[i]]);
			if (img != null)
				ti.setImage(img);
		}
		if (fUpperList.getItemCount() > 0)
			fUpperList.setSelection(0);
		fUpperList.setRedraw(true);
		handleUpperSelectionChanged();
	}
	
	/**
	 * Sent when default selection occurs in the control.
	 * <p>
	 * For example, on some platforms default selection occurs
	 * in a List when the user double-clicks an item or types
	 * return in a Text.
	 * </p>
	 *
	 * @param e an event containing information about the default selection
	 */
	public void widgetDefaultSelected(SelectionEvent e) {
		// Do nothing
	}
	
	/**
	 * Sent when selection occurs in the control.
	 * <p>
	 * For example, on some platforms selection occurs in
	 * a List when the user selects an item or items.
	 * </p>
	 *
	 * @param e an event containing information about the selection
	 */
	public void widgetSelected(SelectionEvent e) {
		if (e.widget == fJSPButton) {
			fSelection = JSP;
			fPageBook.showPage(fJspControl);
			updateOKStatus();
		} else if (e.widget == fServletButton) {
			fSelection = SERVLET;
			fPageBook.showPage(fServletControl);
		} else
			fSelection = -1;
	}
	
	/**
	 * @see ElementTreeSelectionDialog#updateOKStatus()
	 */
	@Override
	protected void updateOKStatus() {
		super.updateOKStatus();
		Button okButton = getOkButton();
		if (okButton != null)
			okButton.setEnabled(fLocalValidator.validate(getResult()).isOK());
	}

	private boolean hasJSPs() {
		WorkbenchContentProvider workbenchContentProvider = new WorkbenchContentProvider();
        Object[] elements = workbenchContentProvider.getElements(fInput);
        if (elements.length > 0) {
        	TypedFileViewerFilter viewerFilter = new TypedFileViewerFilter(getExtensions());
        	elements = viewerFilter.filter(getTreeViewer(), fInput, elements);
        }
        return elements.length != 0;
    }

	/**
     * Sets the tree input.
     * @param input the tree input.
     */
    @Override
	public void setInput(Object input) {
        fInput = input;
        super.setInput(input);
    }
}
