/*******************************************************************************
 * Copyright (c) 2001, 2004 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
 *******************************************************************************/
/*
 *  $RCSfile: BeaninfoPathsBlock.java,v $
 *  $Revision: 1.10 $  $Date: 2005/06/21 19:59:49 $ 
 */
package org.eclipse.jem.internal.beaninfo.ui;


import java.io.File;
import java.lang.reflect.InvocationTargetException;
import java.net.URL;
import java.util.*;
import java.util.List;

import org.eclipse.core.resources.*;
import org.eclipse.core.runtime.*;
import org.eclipse.jdt.core.*;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.JavaPluginImages;
import org.eclipse.jdt.internal.ui.dialogs.StatusInfo;
import org.eclipse.jdt.internal.ui.viewsupport.ImageDisposer;
import org.eclipse.jdt.internal.ui.wizards.IStatusChangeListener;
import org.eclipse.jdt.internal.ui.wizards.dialogfields.*;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.jface.resource.ImageRegistry;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.*;

import org.eclipse.jem.internal.beaninfo.adapters.BeaninfoNature;
import org.eclipse.jem.internal.beaninfo.core.*;
import org.eclipse.jem.internal.ui.core.JEMUIPlugin;

public class BeaninfoPathsBlock {

	private IWorkspaceRoot fWorkspaceRoot;

	private CheckedListDialogField fSearchOrder;
	// Search path list. filtered for each tab page to appropriate entries
	private SelectionButtonDialogField fEnableBeaninfoDialogField;
	// Checkbox to add/remove beaninfo nature entirely.

	private StatusInfo fSearchStatus;

	private IJavaProject fCurrJProject;

	private IStatusChangeListener fContext;
	private PackagesWorkbookPage fPackagesPage;
	private BeaninfosWorkbookPage fBeaninfosPage;

	private BuildSearchBasePage fCurrPage;
	private SearchPathListLabelProvider labelProvider;
	
	public BeaninfoPathsBlock(IWorkspaceRoot root, IStatusChangeListener context) {
		fWorkspaceRoot = root;
		fContext = context;
		fCurrPage = null;

		BuildPathAdapter adapter = new BuildPathAdapter();

		String[] buttonLabels = new String[] {
			BeanInfoUIMessages.BeaninfoPathsBlock_UI__searchpath_up_button, 
			BeanInfoUIMessages.BeaninfoPathsBlock_UI__searchpath_down_button, 
			/* 2 */ null,
			BeanInfoUIMessages.BeanInfoPathsBlock_ExportAll , 
			BeanInfoUIMessages.BeanInfoPathsBlock_UnexportAll
			};
		
		labelProvider = new SearchPathListLabelProvider();	// We keep around to update with latest project.
		fSearchOrder = new CheckedListDialogField(null, buttonLabels, labelProvider);
		fSearchOrder.setDialogFieldListener(adapter);
		fSearchOrder.setLabelText(
			BeanInfoUIMessages.BeaninfoPathsBlock_UI__searchpath_label); 
		fSearchOrder.setUpButtonIndex(0);
		fSearchOrder.setDownButtonIndex(1);
		fSearchOrder.setCheckAllButtonIndex(3);
		fSearchOrder.setUncheckAllButtonIndex(4);

		fEnableBeaninfoDialogField = new SelectionButtonDialogField(SWT.CHECK);
		fEnableBeaninfoDialogField.setLabelText(
			BeanInfoUIMessages.BeaninfoPathsBlock_UI__enablebeaninfo); 

		fSearchStatus = new StatusInfo();

		fCurrJProject = null;
	}
	
	public CheckedListDialogField getSearchOrder() {
		return fSearchOrder;
	}
	
	/*
	 * searchOrder dialog must never have all of elements set
	 * directly. Must come through here first so that we can
	 * make sure updates occur in correct sequence, else
	 * we will wind up with entries being marked as unexported
	 * when they really are exported. 
	 */
	public void setSearchOrderElements(List newElements) {
		ArrayList exportedEntries = new ArrayList(newElements.size());
		for (Iterator iter = newElements.iterator(); iter.hasNext();) {
			BPListElement element = (BPListElement) iter.next();
			if (element.isExported())
				exportedEntries.add(element);
		}
		
		inUpdate = true;	// So that on first set we don't waste time updating the list and reseting all of our entries.
		fSearchOrder.setElements(newElements);
		inUpdate = false;
		fSearchOrder.setCheckedElements(exportedEntries);
	}

	// -------- UI creation ---------

	public Control createControl(Composite parent) {
		Composite composite = new Composite(parent, SWT.NONE);

		GridLayout layout = new GridLayout();
		layout.marginWidth = 0;
		layout.numColumns = 1;
		composite.setLayout(layout);

		TabFolder folder = new TabFolder(composite, SWT.NONE);
		folder.setLayoutData(new GridData(GridData.FILL_BOTH));
		folder.addSelectionListener(new SelectionAdapter() {
			public void widgetSelected(SelectionEvent e) {
				tabChanged(e.item);
			}
		});

		ImageRegistry imageRegistry = JavaPlugin.getDefault().getImageRegistry();

		TabItem item;

		ArrayList interestedDialogFields = new ArrayList(3);

		fPackagesPage = new PackagesWorkbookPage(fWorkspaceRoot, this, interestedDialogFields);
		item = new TabItem(folder, SWT.NONE);
		item.setText(BeanInfoUIMessages.BeanInfoPathsBlock_Page_Tab_Packages); 
		item.setImage(imageRegistry.get(JavaPluginImages.IMG_OBJS_PACKAGE));
		item.setData(fPackagesPage);
		item.setControl(fPackagesPage.getControl(folder));

		// a non shared image
		Image fBeanImage = null;
		URL imageURL = Platform.find(JEMUIPlugin.getPlugin().getBundle(), new Path("icons/javabean.gif")); //$NON-NLS-1$
		if (imageURL != null) 
			fBeanImage = ImageDescriptor.createFromURL(imageURL).createImage();
		else
			fBeanImage = ImageDescriptor.getMissingImageDescriptor().createImage();
		composite.addDisposeListener(new ImageDisposer(fBeanImage));
				
		fBeaninfosPage= new BeaninfosWorkbookPage(fWorkspaceRoot, this, interestedDialogFields);		
		item= new TabItem(folder, SWT.NONE);
		item.setText(BeanInfoUIMessages.BeanInfoPathsBlock_Page_Tab_Classes); 
		item.setImage(fBeanImage);
		item.setData(fBeaninfosPage);
		item.setControl(fBeaninfosPage.getControl(folder));

		// a non shared image
		Image cpoImage = JavaPluginImages.DESC_TOOL_CLASSPATH_ORDER.createImage();
		composite.addDisposeListener(new ImageDisposer(cpoImage));
		
		SearchpathOrderingWorkbookPage ordpage = new SearchpathOrderingWorkbookPage(fSearchOrder, interestedDialogFields);
		item = new TabItem(folder, SWT.NONE);
		item.setText(BeanInfoUIMessages.BeaninfoPathsBlock_UI__serachpath_tab_order); 
		item.setImage(cpoImage);
		item.setData(ordpage);
		item.setControl(ordpage.getControl(folder));

		if (fCurrJProject != null) {
			fPackagesPage.init(fCurrJProject);
			fBeaninfosPage.init(fCurrJProject);
		}

		fEnableBeaninfoDialogField.doFillIntoGrid(composite, 1);
		fEnableBeaninfoDialogField.attachDialogFields((DialogField[]) interestedDialogFields.toArray(new DialogField[interestedDialogFields.size()]));

		folder.setSelection(2);
		fCurrPage = ordpage;
		fSearchOrder.selectFirstElement();

		//		WorkbenchHelp.setHelp(composite, new Object[] { IJavaHelpContextIds.BUILD_PATH_BLOCK });				
		return composite;
	}


	/**
	 * Initializes the classpath for the given project. Multiple calls to init are allowed,
	 * but all existing settings will be cleared and replace by the given or default paths.
	 * @param project The java project to configure.
	 */
	public void init(IJavaProject jproject) {
		fCurrJProject = jproject;
		labelProvider.setJavaProject(jproject);

		try {
			// If we have a config file, we will assume we have a nature. It will add it automatically
			// when we ask for the information. Even if we didn't have the nature, as soon as someone
			// asks for it, we would create it anyhow, and it would use the existing config file.
			// If we don't have a config file, we could have the nature, so we will check for that too.
			boolean haveConfigFile = jproject.getProject().getFile(BeaninfoNature.P_BEANINFO_SEARCH_PATH).exists();
			boolean haveNature = fCurrJProject.getProject().hasNature(BeaninfoNature.NATURE_ID);
			fEnableBeaninfoDialogField.setSelection(haveConfigFile || haveNature);
			if (haveNature || haveConfigFile) {
				BeaninfosDoc doc = BeaninfoNature.getRuntime(fCurrJProject.getProject()).getSearchPath();
				IClasspathEntry[] raw = fCurrJProject.getRawClasspath();

				List newSearchpath = new ArrayList();
				if (doc != null) {
					IBeaninfosDocEntry[] sp = doc.getSearchpath();
					for (int i = 0; i < sp.length; i++) {
						IBeaninfosDocEntry curr = sp[i];
						boolean isMissing = false;
						BPListElement elem = null;
						if (curr instanceof BeaninfoEntry) {
							BeaninfoEntry be = (BeaninfoEntry) curr;

							// get the resource, this tells if the beaninfos exist or not.
							Object[] paths = be.getClasspath(fCurrJProject);
							if (paths != null && paths.length > 0) {
								for (int j = 0; !isMissing && j < paths.length; j++) {
									Object path = paths[i];
									if (path instanceof IProject)
										isMissing = !((IProject) path).exists();
									else if (path instanceof String) {
										File f = new File((String) path);
										isMissing = !f.exists();
									} else if (path instanceof IPath) {
										isMissing = true;	// Plugins are invalid in BeaninfoConfig. They only apply within contributions.
									} else
										isMissing = true; // Invalid, so isMissing.
								}								
							} else
								isMissing = true;

							elem = new BPBeaninfoListElement(be, getInitialSearchpaths(be), isMissing);
						} else {
							// Searchpath entry, see if we can find the raw classpath entry that it is for.
							boolean isExported = false;
							boolean isPackageMissing = true;
							isMissing = true;	// Initially missing until we find it.
							SearchpathEntry ce = (SearchpathEntry) curr;
							int kind = ce.getKind();
							IPath path = ce.getPath();
							for (int j = 0; j < raw.length; j++) {
								if (raw[j].getEntryKind() == kind && raw[j].getPath().equals(path)) {
									isMissing = false;
									isExported = raw[j].isExported() || raw[j].getEntryKind() == IClasspathEntry.CPE_SOURCE;
									String packageName = ce.getPackage();
									if (packageName != null) {
										IPackageFragmentRoot[] roots = fCurrJProject.findPackageFragmentRoots(raw[j]);
										for (int k = 0; k < roots.length; k++) {
											IPackageFragmentRoot iroot = roots[k];
											if (iroot.getPackageFragment(packageName).exists()) {
												isPackageMissing = false;
												break;
											}
										}
									} else
										isPackageMissing = false;
									break;
								}
							}
							elem = new BPSearchListElement(ce, isMissing, isPackageMissing, isExported);
						}

						newSearchpath.add(elem);
					}
				}

				// inits the dialog field
				setSearchOrderElements(newSearchpath);

				if (fPackagesPage != null) {
					fPackagesPage.init(fCurrJProject);
					fBeaninfosPage.init(fCurrJProject);
				}
			} else {
				// No nature, disable,
				fEnableBeaninfoDialogField.setSelection(false);
			}
		} catch (JavaModelException e) {
			fEnableBeaninfoDialogField.setSelection(false);
		} catch (CoreException e) {
			fEnableBeaninfoDialogField.setSelection(false);
		}

//		listenForClasspathChange();
		doStatusLineUpdate();
	}
	
	/*
	 * Create the Searchpath elements for a BeaninfoElement.
	 * Return null if not to update.
	 */
	private BPSearchListElement[] getInitialSearchpaths(BeaninfoEntry infoEntry) {

		// We can only verify the existence of packages within beaninfos that are 
		// located within a project on the desktop. Otherwise we can't find out what
		// packages are in them.
		IPackageFragmentRoot[] roots = null;

		if (infoEntry.getKind() != BeaninfoEntry.BIE_PLUGIN) {
			IClasspathEntry resolved = JavaCore.getResolvedClasspathEntry(infoEntry.getClasspathEntry());
			IResource res = fWorkspaceRoot.findMember(resolved.getPath());
			if (res != null && res.exists()) {
				if (res instanceof IProject) {
					// It is a project itself.
					IJavaProject jp = (IJavaProject) JavaCore.create(res);
					try {
						if (jp != null)
							roots = jp.getPackageFragmentRoots(); // All of the roots in the project are applicable.
					} catch (JavaModelException e) {
					}
				} else {
					// It is within another project
					IProject containingProject = res.getProject();
					IJavaProject jp = JavaCore.create(containingProject);
					if (jp != null) {
						// The roots if this is in the classpath of this project
						try {
							IPackageFragmentRoot root = jp.findPackageFragmentRoot(resolved.getPath());
							if (root != null)
								roots = new IPackageFragmentRoot[] { root };
						} catch (JavaModelException e) {
						}
					}
				}
			}
		}

		SearchpathEntry[] entries = infoEntry.getSearchPaths();
		BPSearchListElement[] packageElements = new BPSearchListElement[entries.length];
		for (int i = 0;
			i < entries.length;
			i++) { // Searchpath entry, see if we can find the raw classpath entry that it is for.
			boolean isPackageMissing = roots != null;
			// If roots is null, then the package isn't missing because we can't test for it.
			SearchpathEntry ce = entries[i];
			if (roots != null) {
				String packageName = ce.getPackage();
				for (int k = 0; k < roots.length; k++) {
					IPackageFragmentRoot iroot = roots[k];
					if (iroot.getPackageFragment(packageName).exists()) {
						isPackageMissing = false;
						break;
					}
				}
			}
			packageElements[i] = new BPSearchListElement(ce, false, isPackageMissing, false);
		}

		return packageElements;
	}

	// -------- public api --------

	/**
	 * Returns the Java project. Can return <code>null<code> if the page has not
	 * been initialized.
	 */
	public IJavaProject getJavaProject() {
		return fCurrJProject;
	}

	private class BuildPathAdapter implements IDialogFieldListener {

		// ---------- IDialogFieldListener --------
		public void dialogFieldChanged(DialogField field) {
			buildPathDialogFieldChanged(field);
		}
	}

	private void buildPathDialogFieldChanged(DialogField field) {
		if (field == fSearchOrder) {
			updateSearchPathStatus();
		}
		doStatusLineUpdate();
	}

	// -------- verification -------------------------------

	private void doStatusLineUpdate() {
		fContext.statusChanged(fSearchStatus);
	}

	private boolean inUpdate;
	// Flag to indicate we are in updateSearchPathStatus and to not do it again. This can
	// happen due to using setCheckedElements instead of setCheckedWithoutUpdate.
	/**
	 * Validates the search path.
	 */
	private void updateSearchPathStatus() {
		if (inUpdate)
			return;
		try {
			inUpdate = true;

			fSearchStatus.setOK();

			List elements = fSearchOrder.getElements();

			boolean entryMissing = false;

			// Because of bug in setcheckedWithoutUpdate, which sets to true no matter what the state is, we need
			// to accumulate the checked elements and re-set them again after this so that they will be correct.	
			ArrayList exported = new ArrayList();

			for (Iterator entries = elements.iterator(); entries.hasNext();) {
				BPListElement currElement = (BPListElement) entries.next();

				boolean isChecked = fSearchOrder.isChecked(currElement);
				if (currElement.canExportBeChanged()) {
					if (isChecked)
						exported.add(currElement);
					currElement.setExported(isChecked);
				} else {
					//				fSearchOrder.setCheckedWithoutUpdate(currElement, currElement.isExported());
					if (currElement.isExported())
						exported.add(currElement);
				}

				entryMissing = entryMissing || currElement.isMissing();
			}

			// Now reset the checked states, due to bug
			fSearchOrder.setCheckedElements(exported);

			if (entryMissing) {
				fSearchStatus.setWarning(
					BeanInfoUIMessages.BeaninfoPathsBlock_UI__warning_EntryMissing); 
			}
		} finally {
			inUpdate = false;
		}
	}

	// -------- creation -------------------------------

	/**
	 * Creates a runnable that sets the configured build paths.
	 */
	public IRunnableWithProgress getRunnable() {
		final boolean wantNature = fEnableBeaninfoDialogField.isSelected();
		final List searchPathEntries = wantNature ? fSearchOrder.getElements() : null;

		return new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException {
				if (monitor == null) {
					monitor = new NullProgressMonitor();
				}
				monitor.beginTask(
					BeanInfoUIMessages.BeaninfoPathsBlock_UI__searchpath_operationdescription, 
					10);
				try {
					setBeaninfoSearchpath(wantNature, searchPathEntries, monitor);
				} catch (CoreException e) {
					throw new InvocationTargetException(e);
				} finally {
					monitor.done();
				}
			}
		};
	}

	private void setBeaninfoSearchpath(
		boolean wantNature,
		List searchPathEntries,
		IProgressMonitor monitor)
		throws CoreException {

		if (wantNature) {
			// create beaninfo nature
			if (!fCurrJProject.getProject().hasNature(BeaninfoNature.NATURE_ID)) {
				addNatureIDToProject(fCurrJProject.getProject(), BeaninfoNature.NATURE_ID, monitor);
			}

			BeaninfoNature nature = BeaninfoNature.getRuntime(fCurrJProject.getProject());
			// Now build/set the search path.
			if (searchPathEntries.size() > 0) {
				IBeaninfosDocEntry[] sparray = new IBeaninfosDocEntry[searchPathEntries.size()];
				Iterator itr = searchPathEntries.iterator();
				int i = 0;
				while (itr.hasNext()) {
					BPListElement elem = (BPListElement) itr.next();
					sparray[i++] = elem.getEntry();
				}
				nature.setSearchPath(new BeaninfosDoc(sparray), monitor);
			} else
				nature.setSearchPath(null, monitor);
		} else {
			// Remove the nature, no longer wanted.
			removeNatureIDFromProject(fCurrJProject.getProject(), BeaninfoNature.NATURE_ID, monitor);
		}
	}

	/**
	 * Adds a nature to a project
	 */
	private void addNatureIDToProject(IProject proj, String natureId, IProgressMonitor monitor)
		throws CoreException {
		IProjectDescription description = proj.getDescription();
		String[] prevNatures = description.getNatureIds();
		String[] newNatures = new String[prevNatures.length + 1];
		System.arraycopy(prevNatures, 0, newNatures, 0, prevNatures.length);
		newNatures[prevNatures.length] = natureId;
		description.setNatureIds(newNatures);
		proj.setDescription(description, monitor);
	}

	private void removeNatureIDFromProject(IProject proj, String natureId, IProgressMonitor monitor)
		throws CoreException {
		IProjectDescription description = proj.getDescription();
		String[] prevNatures = description.getNatureIds();
		int indx = -1;
		for (int i = 0; i < prevNatures.length; i++) {
			if (prevNatures[i].equals(natureId)) {
				indx = i;
				break;
			}
		}
		if (indx == -1)
			return;

		String[] newNatures = new String[prevNatures.length - 1];
		if (newNatures.length != 0) {
			System.arraycopy(prevNatures, 0, newNatures, 0, indx);
			if (indx < newNatures.length)
				System.arraycopy(prevNatures, indx + 1, newNatures, indx, newNatures.length - indx);
		}
		description.setNatureIds(newNatures);
		proj.setDescription(description, monitor);
	}

	// -------- tab switching ----------

	private void tabChanged(Widget widget) {
		if (widget instanceof TabItem) {
			BuildSearchBasePage newPage = (BuildSearchBasePage) ((TabItem) widget).getData();
			if (fCurrPage != null) {
				List selection = fCurrPage.getSelection();
				if (!selection.isEmpty()) {
					newPage.setSelection(selection);
				}
			}
			fCurrPage = newPage;
		}
	}	
}
