/*******************************************************************************
 * Copyright (c) 2016 Andrey Loskutov.
 *
 * 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:
 *     Andrey Loskutov <loskutov@gmx.de> - initial API and implementation
 *******************************************************************************/
package org.eclipse.ui.editors.tests;

import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;

import java.nio.file.Files;
import java.nio.file.attribute.FileTime;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicBoolean;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

import org.eclipse.swt.widgets.Display;

import org.eclipse.core.internal.localstore.FileSystemResourceManager;
import org.eclipse.core.internal.resources.File;
import org.eclipse.core.internal.resources.Workspace;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILog;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.runtime.jobs.Job;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IFolder;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.resources.WorkspaceJob;

import org.eclipse.core.filebuffers.tests.ResourceHelper;

import org.eclipse.jface.action.IStatusLineManager;

import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IWorkbench;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.IWorkbenchWindow;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.ide.IDE;
import org.eclipse.ui.internal.dialogs.EventLoopProgressMonitor;
import org.eclipse.ui.intro.IIntroManager;
import org.eclipse.ui.intro.IIntroPart;

import org.eclipse.ui.editors.text.FileDocumentProvider;

/**
 * Test checking UI deadlock on modifying the FileDocumentProvider's underlined
 * file.
 *
 * @since 3.10
 */
public class FileDocumentProviderTest {

	private File file;
	private AtomicBoolean stoppedByTest;
	private AtomicBoolean stopLockingFlag;
	private LockJob lockJob;
	private LockJob2 lockJob2;
	private FileDocumentProviderMock fileProvider;
	private FileSystemResourceManager fsManager;
	private IEditorPart editor;
	private IWorkbenchPage page;

	@Before
	public void setUp() throws Exception {
		closeIntro(PlatformUI.getWorkbench());
		IFolder folder = ResourceHelper.createFolder("FileDocumentProviderTestProject/test");
		file = (File) ResourceHelper.createFile(folder, "file.txt", "");
		assertTrue(file.exists());
		fsManager = file.getLocalManager();
		assertTrue(fsManager.fastIsSynchronized(file));
		stopLockingFlag = new AtomicBoolean(false);
		stoppedByTest = new AtomicBoolean(false);
		fileProvider = new FileDocumentProviderMock();
		lockJob = new LockJob("Locking workspace", file, stopLockingFlag, stoppedByTest);
		lockJob2 = new LockJob2("Locking workspace", file, stopLockingFlag, stoppedByTest);

		// We need the editor only to get the default editor status line manager
		IWorkbench workbench = PlatformUI.getWorkbench();
		page = workbench.getActiveWorkbenchWindow().getActivePage();
		editor = IDE.openEditor(page, file);
		TestUtil.runEventLoop();

		IStatusLineManager statusLineManager = editor.getEditorSite().getActionBars().getStatusLineManager();
		// This is default monitor which almost all editors are using
		IProgressMonitor progressMonitor = statusLineManager.getProgressMonitor();
		assertNotNull(progressMonitor);
		assertFalse(progressMonitor instanceof NullProgressMonitor);
		assertFalse(progressMonitor instanceof EventLoopProgressMonitor);

		// Because this monitor is not EventLoopProgressMonitor, it will not
		// process UI events while waiting on workspace lock
		fileProvider.setProgressMonitor(progressMonitor);

		TestUtil.waitForJobs(500, 5000);
		Job[] jobs = Job.getJobManager().find(null);
		String jobsList = Arrays.toString(jobs);
		System.out.println("Still running jobs: " + jobsList);
		if (!Job.getJobManager().isIdle()) {
			jobs = Job.getJobManager().find(null);
			for (Job job : jobs) {
				System.out.println("Going to cancel: " + job.getName() + " / " + job);
				job.cancel();
			}
		}
	}

	@After
	public void tearDown() throws Exception {
		stopLockingFlag.set(true);
		lockJob.cancel();
		lockJob2.cancel();
		if (editor != null) {
			page.closeEditor(editor, false);
		}
		ResourceHelper.deleteProject(file.getProject().getName());
		TestUtil.runEventLoop();
		TestUtil.cleanUp();
	}

	@Test
	public void testRefreshFileWhileWorkspaceIsLocked1() throws Exception {
		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=482354
		assertNotNull("Test must run in UI thread", Display.getCurrent());

		// Start workspace job which will lock workspace operations on file via
		// rule
		lockJob.schedule();

		// touch the file of the editor
		makeSureResourceIsOutOfDate();

		// Put an UI event in the queue which will stop the workspace lock job
		// after a delay so that we can verify the UI events are still
		// dispatched after the call to refreshFile() below
		Display.getCurrent().timerExec(500, () -> {
			stopLockingFlag.set(true);
			System.out.println("UI event dispatched, lock removed");
		});

		// Original code will lock UI thread here because it will try to acquire
		// resource lock and no one will process UI events anymore
		fileProvider.refreshFile(file);

		System.out.println("Busy wait terminated, UI thread is operable again!");
		assertFalse("Test deadlocked while waiting on resource lock", stoppedByTest.get());
		assertTrue(stopLockingFlag.get());
	}

	@Test
	public void testRefreshFileWhileWorkspaceIsLocked2() throws Exception {
		// See https://bugs.eclipse.org/bugs/show_bug.cgi?id=482354
		assertNotNull("Test must run in UI thread", Display.getCurrent());

		// Start workspace job which will lock workspace operations on file via
		// rule
		lockJob.schedule();

		// touch the file of the editor
		makeSureResourceIsOutOfDate();

		// Put an UI event in the queue which will stop the workspace lock job
		// after a delay so that we can verify the UI events are still
		// dispatched after the call to refreshFile() below
		Display.getCurrent().timerExec(500, () -> {
			stopLockingFlag.set(true);
			System.out.println("UI event dispatched, lock removed");
		});

		// Original code will lock UI thread here because it will try to acquire
		// resource lock and no one will process UI events anymore
		fileProvider.refreshFile(file, fileProvider.getProgressMonitor());

		System.out.println("Busy wait terminated, UI thread is operable again!");

		assertFalse("Test deadlocked while waiting on resource lock", stoppedByTest.get());
		assertTrue(stopLockingFlag.get());
	}

	@Test
	public void testValidateStateForFileWhileWorkspaceIsLocked() throws Exception {
		assertNotNull("Test must run in UI thread", Display.getCurrent());

		// Start workspace job which will lock workspace operations on file
		lockJob2.schedule();

		Thread.sleep(100);

		// Put an UI event in the queue which will stop the workspace lock job
		// after a delay
		Display.getCurrent().timerExec(600, () -> {
			stopLockingFlag.set(true);
			System.out.println("UI event dispatched, lock removed");
		});

		// Original code will lock UI thread here because it will try to acquire
		// workspace lock and no one will process UI events anymore
		fileProvider.validateState(editor.getEditorInput(), editor.getSite().getShell());

		System.out.println("Busy wait terminated, UI thread is operable again!");
		assertFalse("Test deadlocked while waiting on resource lock", stoppedByTest.get());
		assertTrue(stopLockingFlag.get());
	}

	/*
	 * Set current time stamp via java.nio to make sure
	 * org.eclipse.core.internal.resources.File.refreshLocal(int,
	 * IProgressMonitor) will call super.refreshLocal(IResource.DEPTH_ZERO,
	 * monitor) and so lock the UI by trying to access resource locked by the
	 * job
	 */
	private void makeSureResourceIsOutOfDate() throws Exception {
		int count = 0;
		Files.setLastModifiedTime(file.getLocation().toFile().toPath(),
				FileTime.fromMillis(System.currentTimeMillis()));
		// Give the file system a chance to have a *different* timestamp
		Thread.sleep(100);
		while (fsManager.fastIsSynchronized(file) && count < 1000) {
			Files.setLastModifiedTime(file.getLocation().toFile().toPath(),
					FileTime.fromMillis(System.currentTimeMillis()));
			Thread.sleep(10);
			count++;
		}
		System.out.println("Managed to update file after " + count + " attempts");
		assertFalse(fsManager.fastIsSynchronized(file));
	}

	static void logError(String message, Exception ex) {
		String PLUGIN_ID = "org.eclipse.jface.text"; //$NON-NLS-1$
		ILog log = Platform.getLog(Platform.getBundle(PLUGIN_ID));
		log.log(new Status(IStatus.ERROR, PLUGIN_ID, IStatus.OK, message, ex));
	}

	static void closeIntro(final IWorkbench wb) {
		IWorkbenchWindow window = wb.getActiveWorkbenchWindow();
		if (window != null) {
			IIntroManager im = wb.getIntroManager();
			IIntroPart intro = im.getIntro();
			if (intro != null) {
				im.closeIntro(intro);
			}
		}
	}
}

class FileDocumentProviderMock extends FileDocumentProvider {

	/**
	 * Overridden to make public accessible for the test
	 */
	@Override
	public void refreshFile(IFile file) throws CoreException {
		System.out.println("Will try to refresh file now: " + file);
		super.refreshFile(file);
	}

	/**
	 * Overridden to make public accessible for the test
	 */
	@Override
	public void refreshFile(IFile file, IProgressMonitor m) throws CoreException {
		System.out.println("Will try to refresh file (with monitor: " + m + " ) now: " + file);
		super.refreshFile(file, m);
	}
}

/** Emulates what SVN plugin jobs are doing */
class LockJob extends WorkspaceJob {

	final IResource resource;
	AtomicBoolean stopFlag;
	AtomicBoolean stoppedByTest;

	public LockJob(String name, IResource resource, AtomicBoolean stopFlag, AtomicBoolean stoppedByTest) {
		super(name);
		this.stopFlag = stopFlag;
		this.stoppedByTest = stoppedByTest;
		setUser(true);
		setSystem(true);
		this.resource = resource;
	}

	public IStatus run2() {
		long startTime = System.currentTimeMillis();
		// Wait maximum 5 minutes
		int maxWaitTime = 5 * 60 * 1000;
		long stopTime = startTime + maxWaitTime;

		System.out.println("Starting the busy wait while holding lock on: " + resource.getFullPath());
		try {
			while (!stopFlag.get()) {
				try {
					if (System.currentTimeMillis() > stopTime) {
						FileDocumentProviderTest.logError("Tiemout occured while waiting on test to finish",
								new IllegalStateException());
						stoppedByTest.set(true);
						return Status.CANCEL_STATUS;
					}
					Thread.sleep(100);
				} catch (InterruptedException e) {
					stoppedByTest.set(true);
					FileDocumentProviderTest.logError("Lock job was interrupted while waiting on test to finish", e);
					e.printStackTrace();
					return Status.CANCEL_STATUS;
				}
			}
		} finally {
			System.out.println("Lock task terminated");
		}
		return Status.OK_STATUS;
	}

	@Override
	public boolean belongsTo(Object family) {
		return super.belongsTo(family) || LockJob.class == family;
	}

	@Override
	public String toString() {
		return super.toString() + " on " + resource;
	}

	@Override
	public IStatus runInWorkspace(IProgressMonitor monitor) throws CoreException {
		IWorkspaceRunnable workspaceRunnable = pm -> {
			try {
				run2();
			} catch (Exception e) {
				// Re-throw as OperationCanceledException, which will be
				// caught and re-thrown as InterruptedException below.
				throw new OperationCanceledException(e.getMessage());
			}
			// CoreException and OperationCanceledException are propagated
		};
		ResourcesPlugin.getWorkspace().run(workspaceRunnable,
				resource, IResource.NONE, monitor);

		return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
	}

}

/** Emulates what AutoBuildJob is doing */
class LockJob2 extends Job {

	final IResource resource;
	AtomicBoolean stopFlag;
	AtomicBoolean stoppedByTest;

	public LockJob2(String name, IResource resource, AtomicBoolean stopFlag, AtomicBoolean stoppedByTest) {
		super(name);
		this.stopFlag = stopFlag;
		this.stoppedByTest = stoppedByTest;
		setUser(true);
		setSystem(true);
		this.resource = resource;
		setRule(ResourcesPlugin.getWorkspace().getRoot());
	}

	@Override
	public boolean belongsTo(Object family) {
		return super.belongsTo(family) || LockJob2.class == family;
	}

	@Override
	public IStatus run(IProgressMonitor monitor) {
		Workspace workspace = (Workspace) ResourcesPlugin.getWorkspace();
		try {
			workspace.prepareOperation(getRule(), monitor);
			workspace.beginOperation(true);
			run2();
		} catch (CoreException e) {
			FileDocumentProviderTest.logError(e.getMessage(), e);
		} finally {
			try {
				workspace.endOperation(getRule(), false);
			} catch (CoreException e) {
				FileDocumentProviderTest.logError(e.getMessage(), e);
			}
		}
		return monitor.isCanceled() ? Status.CANCEL_STATUS : Status.OK_STATUS;
	}

	public IStatus run2() {
		long startTime = System.currentTimeMillis();
		// Wait maximum 5 minutes
		int maxWaitTime = 5 * 60 * 1000;
		long stopTime = startTime + maxWaitTime;

		System.out.println("Starting the busy wait while holding lock on: " + resource.getFullPath());
		try {
			while (!stopFlag.get()) {
				try {
					if (System.currentTimeMillis() > stopTime) {
						FileDocumentProviderTest.logError("Tiemout occured while waiting on test to finish",
								new IllegalStateException());
						stoppedByTest.set(true);
						return Status.CANCEL_STATUS;
					}
					Thread.sleep(100);
				} catch (InterruptedException e) {
					stoppedByTest.set(true);
					FileDocumentProviderTest.logError("Lock job was interrupted while waiting on test to finish", e);
					e.printStackTrace();
					return Status.CANCEL_STATUS;
				}
			}
		} finally {
			System.out.println("Lock task terminated");
		}
		return Status.OK_STATUS;
	}
}
