/*******************************************************************************
 * Copyright (c) 2022 Simeon Andreev 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:
 *     Simeon Andreev - initial API and implementation
 *******************************************************************************/

package org.eclipse.ui.tests.largefile;

import static org.junit.Assert.assertArrayEquals;

import java.io.ByteArrayInputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Optional;

import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IProject;
import org.eclipse.core.resources.IWorkspace;
import org.eclipse.core.resources.IWorkspaceRoot;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.ILogListener;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.preference.PreferenceDialog;
import org.eclipse.jface.preference.PreferencePage;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.ui.IEditorDescriptor;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.IEditorRegistry;
import org.eclipse.ui.IPathEditorInput;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.dialogs.PreferencesUtil;
import org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler;
import org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.FileLimit;
import org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.LargeFileEditorSelectionDialog;
import org.eclipse.ui.internal.LargeFileLimitsPreferenceHandler.PromptForEditor;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.tests.harness.util.UITestCase;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.JUnit4;

/**
 * Tests for the large file associations preference added for bug 577289.
 *
 * @since 3.5
 *
 */
@RunWith(JUnit4.class)
public class LargeFileLimitsPreferenceHandlerTest extends UITestCase {

	public static final String TEST_EDITOR_ID1 = "org.eclipse.ui.tests.largefile.testeditor1";
	public static final String TEST_EDITOR_ID2 = "org.eclipse.ui.tests.largefile.testeditor2";

	private static final int DEFALT_LIMIT_VALUE = 8 * 1024 * 1024;

	private static final String TXT_EXTENSION = "txt";
	private static final String XML_EXTENSION = "xml";

	private final IProgressMonitor monitor;
	private IProject testProject;
	private IFile temporaryFile;
	private TestPromptForEditor testPromptForEditor;
	private LargeFileLimitsPreferenceHandler preferenceHandler;
	private IEditorInput testEditorInput;
	private TestLogListener logListener;

	public LargeFileLimitsPreferenceHandlerTest() {
		super(LargeFileLimitsPreferenceHandlerTest.class.getSimpleName());
		monitor = new NullProgressMonitor();
	}

	@Override
	protected void doSetUp() throws Exception {
		super.doSetUp();
		createTestFile();
		testPromptForEditor = new TestPromptForEditor();
		preferenceHandler = new LargeFileLimitsPreferenceHandler(testPromptForEditor);
		testEditorInput = new FileEditorInput(temporaryFile);
		logListener = new TestLogListener();
		Platform.addLogListener(logListener);
	}

	private void createTestFile() throws CoreException {
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IWorkspaceRoot workspaceRoot = workspace.getRoot();
		testProject = workspaceRoot.getProject("SomeProject");
		testProject.create(monitor);
		testProject.open(monitor);
		IPath path = new Path("/" + testProject.getName() + "/test_file" + "." + TXT_EXTENSION);
		temporaryFile = workspaceRoot.getFile(path);
		String content = String.join(System.lineSeparator(), "some line 1", "some line 2");
		boolean force = true;
		temporaryFile.create(new ByteArrayInputStream(content.getBytes()), force, monitor);
	}

	@Override
	protected void doTearDown() throws Exception {
		try {
			Platform.removeLogListener(logListener);
			setDefaultPreferences();
			preferenceHandler.dispose();
			deleteTestFile();
			boolean save = false;
			closeAllEditors(save);
		} finally {
			super.doTearDown();
		}
	}

	private void deleteTestFile() throws CoreException {
		boolean force = true;
		temporaryFile.delete(force, monitor);
		testProject.delete(force, monitor);
	}

	@Test
	public void testPreferencePageSmokeTest() throws Throwable {
		String pageId = LargeFileLimitsPreferenceHandler.LARGE_FILE_ASSOCIATIONS_PREFERENCE_PAGE_ID;
		Shell shell = getWorkbench().getActiveWorkbenchWindow().getShell();
		PreferenceDialog dialog = PreferencesUtil.createPreferenceDialogOn(shell, pageId, null, null);
		try {
			waitForJobs();
			dialog.setBlockOnOpen(false);
			dialog.open();
			waitForJobs();
			PreferencePage page = (PreferencePage) dialog.getSelectedPage();
			// close
			page.performOk();
			waitForJobs();
		} finally {
			dialog.close();
			logListener.assertNoLoggedErrors();
		}
	}

	@Test
	public void testEditorPromptDialogSmokeTest() throws Throwable {
		boolean closedDialog = false;
		long fileSize = 4L;
		Shell shell = getWorkbench().getActiveWorkbenchWindow().getShell();
		LargeFileEditorSelectionDialog dialog = new LargeFileEditorSelectionDialog(shell, TXT_EXTENSION, fileSize);
		try {
			waitForJobs();
			dialog.setBlockOnOpen(false);
			dialog.open();
			waitForJobs();
			dialog.close();
			closedDialog = true;
			IEditorDescriptor selectedEditor = dialog.getSelectedEditor();
			boolean rememberSelection = dialog.shouldRememberSelectedEditor();
			assertNull("Expected no default selection in dialog", selectedEditor);
			assertFalse("Expected default to not remember editor selection", rememberSelection);
			waitForJobs();
		} finally {
			if (!closedDialog) {
				dialog.close();
			}
			logListener.assertNoLoggedErrors();
		}
	}

	@Test
	public void testOpenEditorWithIgnoreSize() throws Exception {
		String testEditorId = TEST_EDITOR_ID2;
		long fileSize = 4L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId, fileSize));
		configureFileLimits(fileLimits);

		Class<?> expectedEditorClass = org.eclipse.ui.tests.api.MockEditorPart.class;
		IEditorInput editorInput = testEditorInput;
		String editorIdForOpen = "org.eclipse.ui.tests.api.MockEditorPart1";

		IWorkbenchPage page = getWorkbench().getActiveWorkbenchWindow().getActivePage();
		IEditorPart editor = null;
		try {
			boolean activate = true;
			int flags = IWorkbenchPage.MATCH_NONE | IWorkbenchPage.MATCH_IGNORE_SIZE;
			editor = page.openEditor(editorInput, editorIdForOpen, activate, flags);
			assertEquals("Wrong editor opened", expectedEditorClass, editor.getClass());
		} finally {
			if (editor != null) {
				editor.dispose();
			}
		}
	}

	@Test
	public void testDisabledDefaultLimit() throws Exception {
		String testEditorId = "org.eclipse.ui.tests.api.MockEditorPart1";
		long fileSize = 1L;
		LargeFileLimitsPreferenceHandler.setDefaultLimit(fileSize);
		LargeFileLimitsPreferenceHandler.disableDefaultLimit();

		IEditorRegistry editorRegistry = getWorkbench().getEditorRegistry();
		IEditorDescriptor testEditor = editorRegistry.findEditor(testEditorId);
		assertNotNull("Expected to find editor with ID: " + testEditorId, testEditor);

		testPromptForEditor.selectedEditor = testEditor;
		testPromptForEditor.rememberSelection = false;
		// bug 579119: dialog to chose editor should not come up, we disabled the
		// default limit preference
		assertNoEditorIsChosen();
	}

	@Test
	public void testOpenEditor() throws Exception {
		String testEditorId = "org.eclipse.ui.tests.api.MockEditorPart1";
		long fileSize = 4L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId, fileSize));
		configureFileLimits(fileLimits);

		Class<?> expectedEditorClass = org.eclipse.ui.tests.api.MockEditorPart.class;
		IEditorInput editorInput = testEditorInput;
		String editorIdForOpen = TEST_EDITOR_ID2;

		IWorkbenchPage page = getWorkbench().getActiveWorkbenchWindow().getActivePage();
		IEditorPart editor = null;
		try {
			editor = page.openEditor(editorInput, editorIdForOpen);
			assertEquals("Wrong editor opened", expectedEditorClass, editor.getClass());
		} finally {
			if (editor != null) {
				editor.dispose();
			}
		}
	}

	@Test
	public void testOpenFileFromDeletedProject() throws Exception {
		IWorkspace workspace = ResourcesPlugin.getWorkspace();
		IWorkspaceRoot root = workspace.getRoot();
		String projectName = LargeFileLimitsPreferenceHandlerTest.class.getSimpleName() + "TestProject";
		IProject project = root.getProject(projectName);
		assertFalse("Expected project to not exist yet: " + projectName, project.exists());
		NullProgressMonitor monitor = new NullProgressMonitor();
		project.create(monitor);
		project.open(monitor);
		assertTrue("Expected project to be accessible: " + projectName, project.isAccessible());
		assertTrue("Expected project to exist: " + projectName, project.exists());

		IFile testFile = project.getFile("test_file.txt");
		ByteArrayInputStream input = new ByteArrayInputStream("test contents".getBytes());
		boolean force = true;
		testFile.create(input, force, monitor);
		IPathEditorInput editorInput = new FileEditorInput(testFile);
		project.delete(force, monitor);
		waitForJobs();

		String testEditorId = "org.eclipse.ui.tests.api.MockEditorPart1";
		long fileSize = 4L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId, fileSize));
		configureFileLimits(fileLimits);

		// we expect the "error editor" to be opened here, as the file we want to open was deleted
		Class<?> expectedEditorClass = org.eclipse.ui.internal.ErrorEditorPart.class;
		String editorIdForOpen = TEST_EDITOR_ID2;
		IWorkbenchPage page = getWorkbench().getActiveWorkbenchWindow().getActivePage();
		IEditorPart editor = null;
		try {
			editor = page.openEditor(editorInput, editorIdForOpen);
			assertEquals("Wrong editor opened", expectedEditorClass, editor.getClass());
		} finally {
			if (editor != null) {
				editor.dispose();
			}
		}
	}

	@Test
	public void testRestoreDefaults() throws Exception {
		String[] configuredExtensions = { TXT_EXTENSION, XML_EXTENSION };
		String[] disabledExtensions = { XML_EXTENSION };
		LargeFileLimitsPreferenceHandler.setConfiguredExtensionTypes(configuredExtensions);
		LargeFileLimitsPreferenceHandler.setDisabledExtensionTypes(disabledExtensions);
		long fileSize = 4L;
		LargeFileLimitsPreferenceHandler.setDefaultLimit(fileSize);
		String testEditorId1 = TEST_EDITOR_ID1;
		long fileSize1 = 4_000L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId1, fileSize1));
		configureFileLimits(fileLimits);

		LargeFileLimitsPreferenceHandler.restoreDefaults();

		doTestDefaults();
	}

	@Test
	public void testDefaults() throws Exception {
		doTestDefaults();
	}

	@Test
	public void testSetConfiguredExtensions() throws Exception {
		String[] extensions = { TXT_EXTENSION, XML_EXTENSION };
		LargeFileLimitsPreferenceHandler.setConfiguredExtensionTypes(extensions);
		String[] configuredExtensions = LargeFileLimitsPreferenceHandler.getConfiguredExtensionTypes();
		assertArrayEquals("Wrong configured extensions", extensions, configuredExtensions);
	}

	@Test
	public void testSetDisabledExtensions() throws Exception {
		String[] extensions = { TXT_EXTENSION, XML_EXTENSION };
		LargeFileLimitsPreferenceHandler.setDisabledExtensionTypes(extensions);
		String[] configuredExtensions = LargeFileLimitsPreferenceHandler.getDisabledExtensionTypes();
		assertArrayEquals("Wrong disabled extensions", extensions, configuredExtensions);
	}

	@Test
	public void testGetEditorForInput() throws Exception {
		long fileSize = 4L;
		LargeFileLimitsPreferenceHandler.setDefaultLimit(fileSize);
		String testEditorId = TEST_EDITOR_ID1;

		IEditorRegistry editorRegistry = getWorkbench().getEditorRegistry();
		IEditorDescriptor testEditor = editorRegistry.findEditor(testEditorId);
		assertNotNull("Expected to find editor with ID: " + testEditorId, testEditor);

		testPromptForEditor.selectedEditor = testEditor;
		testPromptForEditor.rememberSelection = false;
		assertEditorIsChosen(testEditorId);

		List<FileLimit> limits = LargeFileLimitsPreferenceHandler.getLargeFilePreferenceValues(TXT_EXTENSION);
		assertEquals("Expected exactly 1 file limit to be set, but got: " + limits, 1, limits.size());
		FileLimit limit = limits.get(0);
		assertEquals("Wrong limit editor ID",
				LargeFileLimitsPreferenceHandler.PROMPT_EDITOR_PREFERENCE_VALUE, limit.editorId);
		assertEquals("Wrong limit file size", fileSize, limit.fileSize);
	}

	@Test
	public void testRememberSelection() throws Exception {
		long fileSize = 4L;
		LargeFileLimitsPreferenceHandler.setDefaultLimit(fileSize);
		String testEditorId = TEST_EDITOR_ID1;

		IEditorRegistry editorRegistry = getWorkbench().getEditorRegistry();
		IEditorDescriptor testEditor = editorRegistry.findEditor(testEditorId);
		assertNotNull("Expected to find editor with ID: " + testEditorId, testEditor);

		testPromptForEditor.selectedEditor = testEditor;
		testPromptForEditor.rememberSelection = true;
		assertEditorIsChosen(testEditorId);

		List<FileLimit> limits = LargeFileLimitsPreferenceHandler.getLargeFilePreferenceValues(TXT_EXTENSION);
		assertEquals("Expected exactly 1 file limit to be set: " + limits, 1, limits.size());
		FileLimit limit = limits.get(0);
		assertEquals("Wrong limit editor ID remembered", testEditorId, limit.editorId);
		assertEquals("Wrong limit file size remembered", fileSize, limit.fileSize);
	}

	@Test
	public void testNoConfiguration() throws Exception {
		assertNoEditorIsChosen();
	}

	@Test
	public void testDefaultLimit() throws Exception {
		long fileSize = 4L;
		LargeFileLimitsPreferenceHandler.setDefaultLimit(fileSize);

		List<FileLimit> limits = LargeFileLimitsPreferenceHandler.getLargeFilePreferenceValues(TXT_EXTENSION);
		assertEquals("Expected only default file limit, but got: " + limits, 1, limits.size());

		FileLimit defaultLimit = limits.get(0);
		assertEquals("Wrong editor ID",
				LargeFileLimitsPreferenceHandler.PROMPT_EDITOR_PREFERENCE_VALUE, defaultLimit.editorId);
		assertEquals("Wrong file size limit", fileSize, defaultLimit.fileSize);
	}

	@Test
	public void testSingleLimitForExtension() throws Exception {
		String testEditorId = TEST_EDITOR_ID1;
		long fileSize = 4L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId, fileSize));
		configureFileLimits(fileLimits);

		assertEditorIsChosen(testEditorId);
	}

	@Test
	public void testMultipleLimitsForExtension() throws Exception {
		String testEditorId1 = TEST_EDITOR_ID1;
		long fileSize1 = 4L;
		String testEditorId2 = TEST_EDITOR_ID2;
		long fileSize2 = 8L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId1, fileSize1), new FileLimit(testEditorId2, fileSize2));
		configureFileLimits(fileLimits);

		// editor for largest matching file limit should be chosen
		assertEditorIsChosen(testEditorId2);
	}

	@Test
	public void testNoMatchingLimit() throws Exception {
		String testEditorId1 = TEST_EDITOR_ID1;
		long fileSize1 = 4_000L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId1, fileSize1));
		configureFileLimits(fileLimits);

		assertNoEditorIsChosen();
	}

	@Test
	public void testSingleFileLimitAndDefault() throws Exception {
		long defaultLimit = 4L;
		LargeFileLimitsPreferenceHandler.setDefaultLimit(defaultLimit);

		String testEditorId = TEST_EDITOR_ID1;
		long fileSize = 1L;
		List<FileLimit> fileLimits = Arrays.asList(new FileLimit(testEditorId, fileSize));
		configureFileLimits(fileLimits);

		assertEditorIsChosen(testEditorId);
	}

	private void doTestDefaults() {
		String[] configuredExtensionTypes = LargeFileLimitsPreferenceHandler.getConfiguredExtensionTypes();
		assertEmptyArray("Expected no large file associations to be configured by default", configuredExtensionTypes);

		String[] disabledExtensionTypes = LargeFileLimitsPreferenceHandler.getDisabledExtensionTypes();
		assertEmptyArray("Expected no large file associations to be disabled by default", disabledExtensionTypes);

		String extension = TXT_EXTENSION;
		List<FileLimit> limits = LargeFileLimitsPreferenceHandler.getFileLimitsForExtension(extension);
		assertEquals("Expected no limit to be configured per default for file of type: " + extension,
				Collections.EMPTY_LIST, limits);

		boolean defaultLimitEnabled = LargeFileLimitsPreferenceHandler.isDefaultLimitEnabled();
		assertFalse("Expected default large file limit to be disabled", defaultLimitEnabled);
		long defaultLimit = LargeFileLimitsPreferenceHandler.getDefaultLimit();
		assertEquals("Wrong default large file limit value", DEFALT_LIMIT_VALUE, defaultLimit);
	}

	private void assertNoEditorIsChosen() {
		Optional<String> editorForInput = preferenceHandler.getEditorForInput(testEditorInput);
		assertNotNull("Expected non-null result for large file of type: " + TXT_EXTENSION, editorForInput);
		if (editorForInput.isPresent()) {
			fail("Expected no editor for large file of type: " + TXT_EXTENSION + ", but got: " + editorForInput.get());
		}
	}

	private void assertEditorIsChosen(String testEditorId) {
		Optional<String> editorForInput = preferenceHandler.getEditorForInput(testEditorInput);
		assertTrue("Expected editor for large file of type: " + TXT_EXTENSION, editorForInput.isPresent());
		assertEquals("Wrong editor for large file", testEditorId, editorForInput.get());
	}

	private static void waitForJobs() {
		waitForJobs(250, 2_000);
	}

	private static void setDefaultPreferences() {
		LargeFileLimitsPreferenceHandler.setConfiguredExtensionTypes(new String[0]);
		LargeFileLimitsPreferenceHandler.setDisabledExtensionTypes(new String[0]);
		configureFileLimits(Collections.EMPTY_LIST);
		LargeFileLimitsPreferenceHandler.setDefaultLimit(DEFALT_LIMIT_VALUE);
		LargeFileLimitsPreferenceHandler.disableDefaultLimit();
	}

	private static void configureFileLimits(List<FileLimit> fileLimits) {
		LargeFileLimitsPreferenceHandler.setFileLimitsForExtension(TXT_EXTENSION, fileLimits);
		LargeFileLimitsPreferenceHandler.setFileLimitsForExtension(XML_EXTENSION, fileLimits);
	}

	private static void assertEmptyArray(String failMessage, String[] configuredExtensionTypes) {
		assertEquals(failMessage, Collections.EMPTY_LIST, Arrays.asList(configuredExtensionTypes));
	}

	private static void closeAllEditors(boolean save) {
		PlatformUI.getWorkbench().getActiveWorkbenchWindow().getActivePage().closeAllEditors(save);
	}

	private static class TestLogListener implements ILogListener {

		private final List<IStatus> errors = new ArrayList<>();

		@Override
		public void logging(IStatus status, String plugin) {
			if (status.getSeverity() == IStatus.ERROR) {
				errors.add(status);
			}
		}

		void assertNoLoggedErrors() {
			if (!errors.isEmpty()) {
				StringBuilder failMessage = new StringBuilder();
				failMessage.append("Unexpected logged errors:");
				failMessage.append(System.lineSeparator());
				for (IStatus error : errors) {
					failMessage.append("Status message:");
					failMessage.append(error.getMessage());
					failMessage.append(System.lineSeparator());
					failMessage.append("From plug-in:");
					failMessage.append(error.getPlugin());
					failMessage.append(System.lineSeparator());
					Throwable exception = error.getException();
					if (exception != null) {
						failMessage.append("Exception:");
						failMessage.append(System.lineSeparator());
						failMessage.append(exception.getMessage());
						failMessage.append(System.lineSeparator());
						StackTraceElement[] stackTrace = exception.getStackTrace();
						for (StackTraceElement element : stackTrace) {
							failMessage.append('\t');
							failMessage.append(element);
							failMessage.append(System.lineSeparator());
						}
					}

				}
				fail(failMessage.toString());
			}
		}
	}

	private static class TestPromptForEditor implements PromptForEditor {

		IEditorDescriptor selectedEditor = null;
		boolean rememberSelection = false;

		@Override
		public void prompt(IPath inputPath, FileLimit fileLimit) {
			// "selected" editor is set by tests
		}

		@Override
		public IEditorDescriptor getSelectedEditor() {
			return selectedEditor;
		}

		@Override
		public boolean shouldRememberSelectedEditor() {
			return rememberSelection;
		}
	}
}
