/*******************************************************************************
 * Copyright (c) 2000, 2003 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials 
 * are made available under the terms of the Common Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/cpl-v10.html
 * 
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.jdt.internal.junit.wizards;

import java.lang.reflect.InvocationTargetException;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.SubProgressMonitor;

import org.eclipse.swt.widgets.Shell;

import org.eclipse.jface.action.IAction;
import org.eclipse.jface.dialogs.ErrorDialog;
import org.eclipse.jface.dialogs.MessageDialog;
import org.eclipse.jface.dialogs.ProgressMonitorDialog;
import org.eclipse.jface.operation.IRunnableWithProgress;
import org.eclipse.jface.viewers.ILabelProvider;
import org.eclipse.jface.viewers.ISelection;
import org.eclipse.jface.viewers.IStructuredContentProvider;
import org.eclipse.jface.viewers.IStructuredSelection;

import org.eclipse.ui.IObjectActionDelegate;
import org.eclipse.ui.IWorkbenchPart;
import org.eclipse.ui.dialogs.ISelectionStatusValidator;

import org.eclipse.jdt.core.IBuffer;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IPackageFragment;
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.JavaModelException;

import org.eclipse.jdt.ui.JavaElementLabelProvider;

import org.eclipse.jdt.internal.junit.ui.JUnitPlugin;
import org.eclipse.jdt.internal.junit.util.CheckedTableSelectionDialog;
import org.eclipse.jdt.internal.junit.util.ExceptionHandler;
import org.eclipse.jdt.internal.junit.util.JUnitStatus;
import org.eclipse.jdt.internal.junit.util.JUnitStubUtility;
import org.eclipse.jdt.internal.junit.util.Resources;

/**
 * An object contribution action that updates existing AllTests classes.
 */
public class UpdateTestSuite implements IObjectActionDelegate {
	private Shell fShell;
	private IPackageFragment fPack;
	private ICompilationUnit fTestSuite;
	private IMethod fSuiteMethod;
	private static boolean fEmptySelectionAllowed= false;
	private Object[] fSelectedTestCases;

	private class UpdateAllTestsValidator implements ISelectionStatusValidator {	
		/*
		 * @see ISelectionValidator#validate(Object[])
		 */
		public IStatus validate(Object[] selection) {
			int count= 0;
			for (int i= 0; i < selection.length; i++) {
				if (selection[i] instanceof IType) {
					count++;
				}
			}
			if (count == 0 && !fEmptySelectionAllowed) {
				return new JUnitStatus(IStatus.ERROR, ""); //$NON-NLS-1$
			}
			
			IStatus recursiveInclusionStatus= checkRecursiveSuiteInclusion(selection);
			if (recursiveInclusionStatus != null && ! recursiveInclusionStatus.isOK())
				return recursiveInclusionStatus;
				
			String message;
			if (count == 1) {
				message= WizardMessages.getFormattedString("UpdateAllTests.selected_methods.label_one", new Integer(count)); //$NON-NLS-1$
			} else {
				message= WizardMessages.getFormattedString("UpdateAllTests.selected_methods.label_many", new Integer(count)); //$NON-NLS-1$
			}
			return new JUnitStatus(IStatus.INFO, message);
		}
		
		private IStatus checkRecursiveSuiteInclusion(Object[] selection){
			IType suiteClass= fSuiteMethod.getDeclaringType();
			for (int i= 0; i < selection.length; i++) {
				if (selection[i] instanceof IType){
					if (((IType)selection[i]).equals(suiteClass)){
						return new JUnitStatus(IStatus.WARNING, WizardMessages.getString("UpdateTestSuite.infinite_recursion")); //$NON-NLS-1$
					}
				}
			}
			return null;
		}
	}

	public UpdateTestSuite() {
		super();
	}

	/*
	 * @see IObjectActionDelegate#setActivePart(IAction, IWorkbenchPart)
	 */
	public void setActivePart(IAction action, IWorkbenchPart targetPart) {
	}

	/*
	 * @see IActionDelegate#run(IAction)
	 */
	public void run(IAction action) {		
		ILabelProvider lprovider= new JavaElementLabelProvider(JavaElementLabelProvider.SHOW_DEFAULT);
		IStructuredContentProvider cprovider= new NewTestSuiteCreationWizardPage.ClassesInSuitContentProvider();
	
		/* find TestClasses already in Test Suite */
		IType testSuiteType= fTestSuite.findPrimaryType();
		fSuiteMethod= testSuiteType.getMethod("suite", new String[] {}); //$NON-NLS-1$
		if (fSuiteMethod.exists()) {
			try {
			ISourceRange range= fSuiteMethod.getSourceRange();
			IBuffer buf= fTestSuite.getBuffer();
			String originalContent= buf.getText(range.getOffset(), range.getLength());
			buf.close();
			int start= originalContent.indexOf(NewTestSuiteCreationWizardPage.START_MARKER);
			if (start > -1) {
				if (originalContent.indexOf(NewTestSuiteCreationWizardPage.END_MARKER, start) > -1) {
					CheckedTableSelectionDialog dialog= new CheckedTableSelectionDialog(fShell, lprovider, cprovider);
					dialog.setValidator(new UpdateAllTestsValidator());
					dialog.setTitle(WizardMessages.getString("UpdateAllTests.title")); //$NON-NLS-1$
					dialog.setMessage(WizardMessages.getString("UpdateAllTests.message")); //$NON-NLS-1$
					dialog.setInitialSelections(cprovider.getElements(fPack));
					dialog.setSize(60, 25);
					dialog.setInput(fPack);
					if (dialog.open() == CheckedTableSelectionDialog.OK) {
						fSelectedTestCases= dialog.getResult();
						ProgressMonitorDialog progressDialog= new ProgressMonitorDialog(fShell);
						try {
							progressDialog.run(false, false, getRunnable());
						} catch (Exception e) {
							JUnitPlugin.log(e);
						}
					}
				} else {
					cannotUpdateSuiteError();
				}
			} else {
				cannotUpdateSuiteError();
			}
			} catch (JavaModelException e) {
				JUnitPlugin.log(e);
			}
		} else {
			noSuiteError();
		}
	}

	/*
	 * @see IActionDelegate#selectionChanged(IAction, ISelection)
	 */
	public void selectionChanged(IAction action, ISelection selection) {
		fShell= JUnitPlugin.getActiveWorkbenchShell();		
		if (selection instanceof IStructuredSelection) {
			Object testSuiteObj= ((IStructuredSelection) selection).getFirstElement();
			if (testSuiteObj != null && testSuiteObj instanceof ICompilationUnit) {
				fTestSuite= (ICompilationUnit) testSuiteObj;
				IJavaElement packIJE= fTestSuite.getParent();
				if (packIJE instanceof IPackageFragment) {
					fPack= (IPackageFragment) packIJE;
				}
			}
		}
	}
	
	private void updateTestCasesInSuite(IProgressMonitor monitor) {

		try {
			monitor.beginTask(WizardMessages.getString("UpdateAllTests.beginTask"), 5); //$NON-NLS-1$
			if (! checkValidateEditStatus(fTestSuite, fShell))
				return;
				
			ISourceRange range= fSuiteMethod.getSourceRange();
			IBuffer buf= fTestSuite.getBuffer();
			String originalContent= buf.getText(range.getOffset(), range.getLength());
			StringBuffer source= new StringBuffer(originalContent);
			//using JDK 1.4
			//int start= source.toString().indexOf(NewTestSuiteCreationWizardPage.startMarker) --> int start= source.indexOf(NewTestSuiteCreationWizardPage.startMarker)
			int start= source.toString().indexOf(NewTestSuiteCreationWizardPage.START_MARKER);
			if (start > -1) {
				//using JDK 1.4
				//int end= source.toString().indexOf(NewTestSuiteCreationWizardPage.endMarker, start) --> int end= source.indexOf(NewTestSuiteCreationWizardPage.endMarker, start)
				int end= source.toString().indexOf(NewTestSuiteCreationWizardPage.END_MARKER, start);
				if (end > -1) {
					monitor.worked(1);
					end += NewTestSuiteCreationWizardPage.END_MARKER.length();
					//					String updatableCode= source.substring(start,end+NewTestSuiteCreationWizardPage.endMarker.length());
					source.replace(start, end, NewTestSuiteCreationWizardPage.getUpdatableString(fSelectedTestCases));
					buf.replace(range.getOffset(), range.getLength(), source.toString());
					monitor.worked(1);
					fTestSuite.reconcile();
					originalContent= buf.getText(0, buf.getLength());
					monitor.worked(1);
					String formattedContent=
						JUnitStubUtility.codeFormat(
							originalContent,
							0,
							JUnitStubUtility.getLineDelimiterUsed(fTestSuite));
					//buf.replace(range.getOffset(), range.getLength(), formattedContent);
					buf.replace(0, buf.getLength(), formattedContent);
					monitor.worked(1);
					fTestSuite.save(new SubProgressMonitor(monitor, 1), true);
				}
			}
		} catch (JavaModelException e) {
			ExceptionHandler.handle(e, fShell, WizardMessages.getString("UpdateTestSuite.update"), WizardMessages.getString("UpdateTestSuite.error")); //$NON-NLS-1$ //$NON-NLS-2$
		} finally{
			monitor.done();
		}
	}
	
	static boolean checkValidateEditStatus(ICompilationUnit testSuiteCu, Shell shell){
		IStatus status= validateModifiesFiles(getTestSuiteFile(testSuiteCu));
		if (status.isOK())	
			return true;
		ErrorDialog.openError(shell, WizardMessages.getString("UpdateTestSuite.update"), WizardMessages.getString("UpdateTestSuite.could_not_update"), status); //$NON-NLS-1$ //$NON-NLS-2$
		return false;
	}
	
	private static IFile getTestSuiteFile(ICompilationUnit testSuiteCu){
		if (testSuiteCu.isWorkingCopy())
			return (IFile)testSuiteCu.getOriginalElement().getResource();
		else
			return (IFile)testSuiteCu.getResource();
	}
	
	private static IStatus validateModifiesFiles(IFile fileToModify) {
		IFile[] filesToModify= {fileToModify};
		IStatus status= Resources.checkInSync(filesToModify);
		if (! status.isOK())
			return status;
		status= Resources.makeCommittable(filesToModify, null);
		if (! status.isOK())
			return status;
		return new JUnitStatus();
	}

	public IRunnableWithProgress getRunnable() {
		return new IRunnableWithProgress() {
			public void run(IProgressMonitor monitor) throws InvocationTargetException, InterruptedException {
				if (monitor == null) {
					monitor= new NullProgressMonitor();
				}
				updateTestCasesInSuite(monitor);
			}
		};
	}

	private void cannotUpdateSuiteError() {
		MessageDialog.openError(fShell, WizardMessages.getString("UpdateAllTests.cannotUpdate.errorDialog.title"), //$NON-NLS-1$
			WizardMessages.getFormattedString("UpdateAllTests.cannotUpdate.errorDialog.message", new String[] {NewTestSuiteCreationWizardPage.START_MARKER, NewTestSuiteCreationWizardPage.END_MARKER})); //$NON-NLS-1$

	}

	private void noSuiteError() {
		MessageDialog.openError(fShell, WizardMessages.getString("UpdateAllTests.cannotFind.errorDialog.title"), WizardMessages.getString("UpdateAllTests.cannotFind.errorDialog.message")); //$NON-NLS-1$ //$NON-NLS-2$
	}
}
