/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * 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.List;

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.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.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.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.BadLocationException;

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

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.JavaModelException;
import org.eclipse.jdt.core.compiler.InvalidInputException;

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.NLSScanner;
import org.eclipse.jdt.internal.corext.refactoring.reorg.ReorgUtils;
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.ui.JavaElementLabels;

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.refactoring.nls.ExternalizeWizard;
import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
import org.eclipse.jdt.internal.core.manipulation.util.BasicElementLabels;


/**
 * Find all strings in a package or project that are not externalized yet.
 * <p>
 * The action is applicable to selections containing projects or packages.
 *
 * <p>
 * This class may be instantiated; it is not intended to be subclassed.
 * </p>
 *
 * @since 2.0
 * @deprecated use {@link ExternalizeStringsAction} instead
 *
 * @noextend This class is not intended to be subclassed by clients.
 */
@Deprecated
public class FindStringsToExternalizeAction extends SelectionDispatchAction {

	private NonNLSElement[] fElements;

	/**
	 * Creates a new <code>FindStringsToExternalizeAction</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 FindStringsToExternalizeAction(IWorkbenchSite site) {
		super(site);
		setText(ActionMessages.FindStringsToExternalizeAction_label);
		PlatformUI.getWorkbench().getHelpSystem().setHelp(this, IJavaHelpContextIds.FIND_STRINGS_TO_EXTERNALIZE_ACTION);
	}

	@Override
	public void selectionChanged(IStructuredSelection selection) {
		try {
			setEnabled(computeEnablementState(selection));
		} catch (JavaModelException e) {
			if (JavaModelUtil.isExceptionToBeLogged(e))
				JavaPlugin.log(e);
			setEnabled(false);//no UI - happens on selection changes
		}
	}

	private boolean computeEnablementState(IStructuredSelection selection) throws JavaModelException {
		if (selection.isEmpty())
			return false;
		for (Object element : selection) {
			if (!(element instanceof IJavaElement))
				return false;
			IJavaElement javaElement= (IJavaElement)element;
			if (! javaElement.exists() || javaElement.isReadOnly())
				return false;
			int elementType= javaElement.getElementType();
			if (elementType != IJavaElement.PACKAGE_FRAGMENT &&
				elementType != IJavaElement.PACKAGE_FRAGMENT_ROOT &&
				elementType != IJavaElement.JAVA_PROJECT)
				return false;
			if (elementType == IJavaElement.PACKAGE_FRAGMENT_ROOT){
				IPackageFragmentRoot root= (IPackageFragmentRoot)javaElement;
				if (root.isExternal() || ReorgUtils.isClassFolder(root))
					return false;
			}
		}
		return true;
	}

	@Override
	public void run(final IStructuredSelection selection) {
		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();
	}

	private IRunnableWithProgress createRunnable(final IStructuredSelection selection) {
		return new IRunnableWithProgress() {
			@Override
			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<NonNLSElement> l= new ArrayList<>();
			for (Object e : (List<?>)elements) {
				IJavaElement element=(IJavaElement) e;
				if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT)
					l.addAll(analyze((IPackageFragment) element, new SubProgressMonitor(pm, 1)));
				else if (element.getElementType() == IJavaElement.PACKAGE_FRAGMENT_ROOT)
					l.addAll(analyze((IPackageFragmentRoot) element, new SubProgressMonitor(pm, 1)));
				if (element.getElementType() == IJavaElement.JAVA_PROJECT)
					l.addAll(analyze((IJavaProject) element, new SubProgressMonitor(pm, 1)));
			}
			return l.toArray(new NonNLSElement[l.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 (NonNLSElement fElement : fElements) {
				if (fElement.count != 0) {
					return false;
				}
			}
		}
		return true;
	}

	/*
	 * returns List of Strings
	 */
	private List<NonNLSElement> 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<NonNLSElement> l= new ArrayList<>(cus.length);
			for (ICompilationUnit cu : cus) {
				pm.subTask(BasicElementLabels.getFileName(cu));
				NonNLSElement element= analyze(cu);
				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<NonNLSElement> analyze(IPackageFragmentRoot sourceFolder, IProgressMonitor pm) throws CoreException {
		try{
			IJavaElement[] children= sourceFolder.getChildren();
			pm.beginTask("", children.length); //$NON-NLS-1$
			pm.setTaskName(JavaElementLabels.getElementLabel(sourceFolder, JavaElementLabels.ALL_DEFAULT));
			List<NonNLSElement> result= new ArrayList<>();
			for (IJavaElement iJavaElement : children) {
				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<NonNLSElement> analyze(IJavaProject project, IProgressMonitor pm) throws CoreException {
		try{
			IPackageFragment[] packs= project.getPackageFragments();
			pm.beginTask("", packs.length); //$NON-NLS-1$
			List<NonNLSElement> result= new ArrayList<>();
			for (IPackageFragment pack : packs) {
				if (!pack.isReadOnly()) {
					result.addAll(analyze(pack, new SubProgressMonitor(pm, 1)));
				} else {
					pm.worked(1);
				}
			}
			return result;
		} finally{
			pm.done();
		}
	}

	private int countStrings() {
		int found= 0;
		if (fElements != null) {
			for (NonNLSElement fElement : fElements) {
				found+= fElement.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{
			int result= 0;
			for (NLSLine line : NLSScanner.scan(cu)) {
				result += countNonExternalizedStrings(line);
			}
			return result;
		} catch (InvalidInputException e) {
			throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.ERROR,
				Messages.format(ActionMessages.FindStringsToExternalizeAction_error_cannotBeParsed, BasicElementLabels.getFileName(cu)),
				e));
		} catch (BadLocationException e) {
			throw new CoreException(new Status(IStatus.ERROR, JavaPlugin.getPluginId(), IStatus.ERROR, Messages.format(ActionMessages.FindStringsToExternalizeAction_error_cannotBeParsed,
					BasicElementLabels.getFileName(cu)), e));
		}
	}

	private int countNonExternalizedStrings(NLSLine line){
		int result= 0;
		for (NLSElement element : line.getElements()) {
			if (!element.hasTag()) {
				result++;
			}
		}
		return result;
	}

	/**
	 * @param selection the selection
	 * @return 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);
			setAddCancelButton(false);
			setInput(Arrays.asList(input));
			setTitle(ActionMessages.FindStringsToExternalizeAction_dialog_title);
			String message= count == 1 ? ActionMessages.FindStringsToExternalizeAction_non_externalized_singular : Messages.format(
					ActionMessages.FindStringsToExternalizeAction_non_externalized_plural, new Object[] { Integer.valueOf(count) });
			setMessage(message);
			setContentProvider(ArrayContentProvider.getInstance());
			setLabelProvider(createLabelProvider());
		}

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

		@Override
		protected Control createDialogArea(Composite parent) {
			Composite result= (Composite)super.createDialogArea(parent);
			getTableViewer().addSelectionChangedListener(new ISelectionChangedListener(){
				@Override
				public void selectionChanged(SelectionChangedEvent event){
					if (fOpenButton != null){
						fOpenButton.setEnabled(! getTableViewer().getSelection().isEmpty());
					}
				}
			});
			getTableViewer().getTable().addSelectionListener(new SelectionAdapter(){
				@Override
				public void widgetDefaultSelected(SelectionEvent e) {
					NonNLSElement element= (NonNLSElement)e.item.getData();
					ExternalizeWizard.open(element.cu, getShell());
				}
			});
			getTableViewer().getTable().setFocus();
			applyDialogFont(result);
			return result;
		}

		@Override
		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);
		}

		@Override
		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)
					ExternalizeWizard.open(((NonNLSElement) ss.getFirstElement()).cu, getShell());
			}
		}

		private static LabelProvider createLabelProvider() {
			return new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT){
				@Override
				public String getText(Object element) {
					NonNLSElement nlsel= (NonNLSElement)element;
					String elementName= BasicElementLabels.getPathLabel(nlsel.cu.getResource().getFullPath(), false);
					return Messages.format(
						ActionMessages.FindStringsToExternalizeAction_foundStrings,
						new Object[] {Integer.valueOf(nlsel.count), elementName} );
				}
				@Override
				public Image getImage(Object element) {
					return super.getImage(((NonNLSElement)element).cu);
				}
			};
		}

		/*
		 * @see org.eclipse.jface.window.Window#configureShell(Shell)
		 */
		@Override
		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;
	}
}
