/*******************************************************************************
 * Copyright (c) 2000, 2006 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
 *******************************************************************************/
package org.eclipse.jdt.ui.actions;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.SubProgressMonitor;

import org.eclipse.swt.SWT;
import org.eclipse.swt.custom.BusyIndicator;
import org.eclipse.swt.events.SelectionAdapter;
import org.eclipse.swt.events.SelectionEvent;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Button;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.jface.dialogs.IDialogConstants;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ArrayContentProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.ISelectionChangedListener;
import org.eclipse.jface.viewers.IStructuredSelection;
import org.eclipse.jface.viewers.LabelProvider;
import org.eclipse.jface.viewers.SelectionChangedEvent;

import org.eclipse.jface.text.ITextSelection;

import org.eclipse.ui.IWorkbenchSite;
import org.eclipse.ui.PlatformUI;

import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.IPackageFragmentRoot;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.compiler.InvalidInputException;

import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
import org.eclipse.jdt.internal.corext.refactoring.nls.NLSElement;
import org.eclipse.jdt.internal.corext.refactoring.nls.NLSLine;
import org.eclipse.jdt.internal.corext.refactoring.nls.NLSRefactoring;
import org.eclipse.jdt.internal.corext.refactoring.nls.NLSScanner;
import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.ui.JavaElementLabelProvider;

import org.eclipse.jdt.internal.ui.IJavaHelpContextIds;
import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.actions.ActionMessages;
import org.eclipse.jdt.internal.ui.actions.ActionUtil;
import org.eclipse.jdt.internal.ui.actions.SelectionConverter;
import org.eclipse.jdt.internal.ui.javaeditor.CompilationUnitEditor;
import org.eclipse.jdt.internal.ui.refactoring.actions.ListDialog;
import org.eclipse.jdt.internal.ui.refactoring.actions.RefactoringStarter;
import org.eclipse.jdt.internal.ui.refactoring.nls.ExternalizeWizard;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;

/**
 * Externalizes the strings of a compilation unit or find all strings
 * in a package or project that are not externalized yet. Opens a wizard that
 * gathers additional information to externalize the strings.
 * <p>
 * The action is applicable to structured selections containing elements
 * of type <code>ICompilationUnit</code>, <code>IType</code>, <code>IJavaProject</code>,
 * <code>IPackageFragment</code>, and <code>IPackageFragmentRoot</code>
 * 
 * <p>
 * This class may be instantiated; it is not intended to be subclassed.
 * </p>
 *
 * @since 2.0
 */
public class ExternalizeStringsAction extends SelectionDispatchAction {

	private CompilationUnitEditor fEditor;
	
	private NonNLSElement[] fElements;

	/**
	 * Creates a new <code>ExternalizeStringsAction</code>. The action requires
	 * that the selection provided by the site's selection provider is of type <code>
	 * org.eclipse.jface.viewers.IStructuredSelection</code>.
	 * 
	 * @param site the site providing context information for this action
	 */
	public ExternalizeStringsAction(IWorkbenchSite site) {
		super(site);
		setText(ActionMessages.ExternalizeStringsAction_label); 
		PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.EXTERNALIZE_STRINGS_ACTION);
	}

	/**
	 * Note: This constructor is for internal use only. Clients should not call this constructor.
	 * @param editor the compilation unit editor
	 */
	public ExternalizeStringsAction(CompilationUnitEditor editor) {
		this(editor.getEditorSite());
		fEditor= editor;
		setEnabled(fEditor != null && SelectionConverter.canOperateOn(fEditor));
	}
	
	/* (non-Javadoc)
	 * Method declared on SelectionDispatchAction.
	 */
	public void selectionChanged(ITextSelection selection) {
	}
	
	/* (non-Javadoc)
	 * Method declared on SelectionDispatchAction.
	 */
	public void selectionChanged(IStructuredSelection selection) {
		try {
			setEnabled(RefactoringAvailabilityTester.isExternalizeStringsAvailable(selection));
		} catch (JavaModelException e) {
			if (JavaModelUtil.isExceptionToBeLogged(e))
				JavaPlugin.log(e);
			setEnabled(false);//no UI - happens on selection changes
		}
	}

	/* (non-Javadoc)
	 * Method declared on SelectionDispatchAction.
	 */
	public void run(ITextSelection selection) {
		IJavaElement element= SelectionConverter.getInput(fEditor);
		if (!(element instanceof ICompilationUnit))
			return;
		run((ICompilationUnit)element);
	}
	
	/* (non-Javadoc)
	 * Method declared on SelectionDispatchAction.
	 */
	public void run(IStructuredSelection selection) {
		ICompilationUnit unit= getCompilationUnit(selection);
		if (unit != null) {//run on cu 
			run(unit);
		} else {
			//run on multiple
			try {
				PlatformUI.getWorkbench().getProgressService().run(true, true, createRunnable(selection));
			} catch(InvocationTargetException e) {
				ExceptionHandler.handle(e, getShell(), 
					ActionMessages.FindStringsToExternalizeAction_dialog_title, 
					ActionMessages.FindStringsToExternalizeAction_error_message); 
				return;
			} catch(InterruptedException e) {
				// OK
				return;
			}
			showResults();	
		}
	}
	
	/**
	 * Note: this method is for internal use only. Clients should not call this method.
	 */
	public void run(final ICompilationUnit unit) {
		if (!ActionUtil.isProcessable(getShell(), unit))
			return;
		
		BusyIndicator.showWhile(getShell().getDisplay(), new Runnable() {
			public void run() {
				try {
					if (unit != null && unit.exists()) {
						NLSRefactoring refactoring= NLSRefactoring.create(unit);
						if (refactoring != null)
							new RefactoringStarter().activate(refactoring, new ExternalizeWizard(refactoring), getShell(), ActionMessages.ExternalizeStringsAction_dialog_title, true); 
					}
				} catch(JavaModelException e) {
					ExceptionHandler.handle(e, getShell(), ActionMessages.ExternalizeStringsAction_dialog_title, ActionMessages.ExternalizeStringsAction_dialog_message); 
				}
			}
		});
	}

	private static ICompilationUnit getCompilationUnit(IStructuredSelection selection) {
		if (selection.isEmpty() || selection.size() != 1)
			return null;
		Object first= selection.getFirstElement();
		if (first instanceof ICompilationUnit) 
			return (ICompilationUnit) first;
		if (first instanceof IType)
			return ((IType) first).getCompilationUnit();
		return null;
	}
	
	private IRunnableWithProgress createRunnable(final IStructuredSelection selection) {
		return new IRunnableWithProgress() {
			public void run(IProgressMonitor pm) throws InvocationTargetException {
				try {
					fElements= doRun(selection, pm);
				} catch (CoreException e) {
					throw new InvocationTargetException(e);
				}
			}
		};
	}

	private NonNLSElement[] doRun(IStructuredSelection selection, IProgressMonitor pm) throws CoreException {
		List elements= getSelectedElementList(selection);
		if (elements == null || elements.isEmpty())
			return new NonNLSElement[0];

		pm.beginTask(ActionMessages.FindStringsToExternalizeAction_find_strings, elements.size()); 
					
		try{
			List result= new ArrayList();	
			for (Iterator iter= elements.iterator(); iter.hasNext();) {
				Object obj= iter.next();
				if (obj instanceof IJavaElement) {
					IJavaElement element= (IJavaElement) obj;
					int elementType= element.getElementType();
					
					if (elementType == IJavaElement.PACKAGE_FRAGMENT) {
						result.addAll(analyze((IPackageFragment) element, new SubProgressMonitor(pm, 1)));
					} else if (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT) {
						IPackageFragmentRoot root= (IPackageFragmentRoot)element;
						if (!root.isExternal() && !ReorgUtils.isClassFolder(root)) {
							result.addAll(analyze((IPackageFragmentRoot) element, new SubProgressMonitor(pm, 1)));
						} else {
							pm.worked(1);
						}
					} else if (elementType == IJavaElement.JAVA_PROJECT) {
						result.addAll(analyze((IJavaProject) element, new SubProgressMonitor(pm, 1)));
					} else if (elementType == IJavaElement.COMPILATION_UNIT) {
						ICompilationUnit cu= (ICompilationUnit)element;
						if (cu.exists()) {
							NonNLSElement nlsElement= analyze(cu);
							if (nlsElement != null) {
								result.add(nlsElement);
							}							
						}
						pm.worked(1);
					} else if (elementType == IJavaElement.TYPE) {
						IType type= (IType)element;
						ICompilationUnit cu= type.getCompilationUnit();
						if (cu != null && cu.exists()) {
							NonNLSElement nlsElement= analyze(cu);
							if (nlsElement != null) {
								result.add(nlsElement);
							}							
						}
						pm.worked(1);
					} else {
						pm.worked(1);
					}
				} else {
					pm.worked(1);
				}
			}
			return (NonNLSElement[]) result.toArray(new NonNLSElement[result.size()]);
		} finally{
			pm.done();
		}
	}

	private void showResults() {
		if (noStrings())
			MessageDialog.openInformation(getShell(), getDialogTitle(), ActionMessages.FindStringsToExternalizeAction_noStrings); 
		else
			new NonNLSListDialog(getShell(), fElements, countStrings()).open();
	}

	private boolean noStrings() {
		if (fElements != null) {
			for (int i= 0; i < fElements.length; i++) {
				if (fElements[i].count != 0)
					return false;
			}
		}
		return true;
	}

	/*
	 * returns List of Strings
	 */
	private List analyze(IPackageFragment pack, IProgressMonitor pm) throws CoreException {
		try{
			if (pack == null)
				return new ArrayList(0);
				
			ICompilationUnit[] cus= pack.getCompilationUnits();
	
			pm.beginTask("", cus.length); //$NON-NLS-1$
			pm.setTaskName(pack.getElementName());
			
			List l= new ArrayList(cus.length);
			for (int i= 0; i < cus.length; i++){
				pm.subTask(cus[i].getElementName());
				NonNLSElement element= analyze(cus[i]);
				if (element != null)
					l.add(element);
				pm.worked(1);
				if (pm.isCanceled())
					throw new OperationCanceledException();
			}	
			return l;					
		} finally {
			pm.done();
		}	
	}

	/*
	 * returns List of Strings
	 */	
	private List analyze(IPackageFragmentRoot sourceFolder, IProgressMonitor pm) throws CoreException {
		try{
			IJavaElement[] children= sourceFolder.getChildren();
			pm.beginTask("", children.length); //$NON-NLS-1$
			pm.setTaskName(sourceFolder.getElementName());
			List result= new ArrayList();
			for (int i= 0; i < children.length; i++) {
				IJavaElement iJavaElement= children[i];
				if (iJavaElement.getElementType() == IJavaElement.PACKAGE_FRAGMENT){
					IPackageFragment pack= (IPackageFragment)iJavaElement;
					if (! pack.isReadOnly())
						result.addAll(analyze(pack, new SubProgressMonitor(pm, 1)));
					else
						pm.worked(1);	
				} else	
					pm.worked(1);
			}
			return result;
		} finally{
			pm.done();
		}	
	}
	
	/*
	 * returns List of Strings
	 */
	private List analyze(IJavaProject project, IProgressMonitor pm) throws CoreException {
		try{
			IPackageFragment[] packs= project.getPackageFragments();
			pm.beginTask("", packs.length); //$NON-NLS-1$
			List result= new ArrayList();
			for (int i= 0; i < packs.length; i++) {
				if (! packs[i].isReadOnly())
					result.addAll(analyze(packs[i], new SubProgressMonitor(pm, 1)));
				else 
					pm.worked(1);	
			}
			return result;		
		} finally{
			pm.done();
		}	
	}

	private int countStrings() {
		int found= 0;
		if (fElements != null) {
			for (int i= 0; i < fElements.length; i++)
				found+= fElements[i].count;
		}
		return found;
	} 

	private NonNLSElement analyze(ICompilationUnit cu) throws CoreException {
		int count= countNonExternalizedStrings(cu);
		if (count == 0)
			return null;
		else	
			return new NonNLSElement(cu, count);
	}
	
	private int countNonExternalizedStrings(ICompilationUnit cu) throws CoreException {
		try{
			NLSLine[] lines= NLSScanner.scan(cu);
			int result= 0;
			for (int i= 0; i < lines.length; i++) {
				result += countNonExternalizedStrings(lines[i]);
			}
			return result;
		} catch (InvalidInputException e) {
			throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.ERROR,
				Messages.format(ActionMessages.FindStringsToExternalizeAction_error_cannotBeParsed, cu.getElementName()), 
				e));
		}	
	}

	private int countNonExternalizedStrings(NLSLine line){
		int result= 0;
		NLSElement[] elements= line.getElements();
		for (int i= 0; i < elements.length; i++){
			if (! elements[i].hasTag())
				result++;
		}
		return result;
	}

	/**
	 * returns <code>List</code> of <code>IPackageFragments</code>,  <code>IPackageFragmentRoots</code> or 
	 * <code>IJavaProjects</code> (all entries are of the same kind)
	 */
	private static List getSelectedElementList(IStructuredSelection selection) {
		if (selection == null)
			return null;
			
		return selection.toList();
	}
			
	//-------private classes --------------
		
	private static class NonNLSListDialog extends ListDialog {
		
		private static final int OPEN_BUTTON_ID= IDialogConstants.CLIENT_ID + 1;
		
		private Button fOpenButton;
		
		NonNLSListDialog(Shell parent, NonNLSElement[] input, int count) {
			super(parent);
			setInput(Arrays.asList(input));
			setTitle(ActionMessages.ExternalizeStringsAction_dialog_title);  
			setMessage(Messages.format(ActionMessages.FindStringsToExternalizeAction_non_externalized, new Object[] {new Integer(count)} )); 
			setContentProvider(new ArrayContentProvider());
			setLabelProvider(createLabelProvider());
		}

		public void create() {
			setShellStyle(SWT.DIALOG_TRIM | SWT.RESIZE | SWT.MIN);
			super.create();
		}

		protected Point getInitialSize() {
			return getShell().computeSize(SWT.DEFAULT, SWT.DEFAULT, true);
		}

		protected Control createDialogArea(Composite parent) {
			Composite result= (Composite)super.createDialogArea(parent);
			getTableViewer().addSelectionChangedListener(new ISelectionChangedListener(){
				public void selectionChanged(SelectionChangedEvent event){
					if (fOpenButton != null){
						fOpenButton.setEnabled(! getTableViewer().getSelection().isEmpty());
					}
				}
			});
			getTableViewer().getTable().addSelectionListener(new SelectionAdapter(){
				public void widgetDefaultSelected(SelectionEvent e) {
					NonNLSElement element= (NonNLSElement)e.item.getData();
					openWizard(element.cu);
				}
			});
			getTableViewer().getTable().setFocus();
			applyDialogFont(result);		
			return result;
		}
		
		protected void createButtonsForButtonBar(Composite parent) {
			fOpenButton= createButton(parent, OPEN_BUTTON_ID, ActionMessages.FindStringsToExternalizeAction_button_label, true); 
			fOpenButton.setEnabled(false);
			
			//looks like a 'close' but it a 'cancel'
			createButton(parent, IDialogConstants.CANCEL_ID, IDialogConstants.CLOSE_LABEL, false);
		}

		protected void buttonPressed(int buttonId) {
			if (buttonId != OPEN_BUTTON_ID){
				super.buttonPressed(buttonId);
				return;
			}	
			ISelection s= getTableViewer().getSelection();
			if (s instanceof IStructuredSelection){
				IStructuredSelection ss= (IStructuredSelection)s;
				if (ss.getFirstElement() instanceof NonNLSElement)
					openWizard(((NonNLSElement)ss.getFirstElement()).cu);
			}
		}

		private void openWizard(ICompilationUnit unit) {
			try {
				if (unit != null && unit.exists()) {
					NLSRefactoring refactoring= NLSRefactoring.create(unit);
					if (refactoring != null)
						new RefactoringStarter().activate(refactoring, new ExternalizeWizard(refactoring), getShell(), ActionMessages.ExternalizeStringsAction_dialog_title, true); 
				}
			} catch (JavaModelException e) {
				ExceptionHandler.handle(e, 
					ActionMessages.FindStringsToExternalizeAction_dialog_title, 
					ActionMessages.FindStringsToExternalizeAction_error_message); 
			}
		}
		
		private static LabelProvider createLabelProvider() {
			return new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT){ 
				public String getText(Object element) {
					NonNLSElement nlsel= (NonNLSElement)element;
					String elementName= ResourceUtil.getResource(nlsel.cu).getFullPath().toString();
					return Messages.format(
						ActionMessages.FindStringsToExternalizeAction_foundStrings, 
						new Object[] {new Integer(nlsel.count), elementName} );
				}		
				public Image getImage(Object element) {
					return super.getImage(((NonNLSElement)element).cu);
				}
			};
		}
		
		/*
		 * @see org.eclipse.jface.window.Window#configureShell(Shell)
		 */
		protected void configureShell(Shell newShell) {
			super.configureShell(newShell);
			PlatformUI.getWorkbench().getHelpSystem().setHelp(newShell, IJavaHelpContextIds.NONNLS_DIALOG);		
		}


	}
		
	private static class NonNLSElement{
		ICompilationUnit cu;
		int count;
		NonNLSElement(ICompilationUnit cu, int count){
			this.cu= cu;
			this.count= count;
		}
	}
	
	private String getDialogTitle() {
		return ActionMessages.FindStringsToExternalizeAction_dialog_title; 
	}	

}
