/*******************************************************************************
 * Copyright (c) 2000, 2019 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.debug.tests.core;

import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import org.eclipse.core.runtime.Platform;
import org.eclipse.debug.core.DebugPlugin;
import org.eclipse.debug.core.ILaunch;
import org.eclipse.debug.core.ILaunchConfiguration;
import org.eclipse.debug.core.ILaunchConfigurationWorkingCopy;
import org.eclipse.debug.core.ILaunchManager;
import org.eclipse.debug.core.model.IStreamsProxy;
import org.eclipse.debug.core.model.IStreamsProxy2;
import org.eclipse.debug.internal.core.IInternalDebugCoreConstants;
import org.eclipse.debug.internal.ui.DebugUIPlugin;
import org.eclipse.debug.ui.console.IConsole;
import org.eclipse.debug.ui.console.IConsoleLineTrackerExtension;
import org.eclipse.jdt.debug.testplugin.ConsoleLineTracker;
import org.eclipse.jdt.debug.tests.AbstractDebugTest;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.swt.widgets.Display;
import org.eclipse.test.OrderedTestSuite;

import junit.framework.TestSuite;

/**
 * Tests console input.
 */
public class ConsoleInputTests extends AbstractDebugTest implements IConsoleLineTrackerExtension {

	protected List<String> fLinesRead = new ArrayList<>();

	protected boolean fStarted = false;

	protected boolean fStopped = false;

	protected IConsole fConsole = null;

	protected Object fConsoleLock = new Object();
	protected Object fLock = new Object();


	public static TestSuite suite() {
		return new OrderedTestSuite(ConsoleInputTests.class, new String[] {
				"testMultiLineInput",
				"testEOF",
				"testDeleteAllEnteredText",
				"testBug545769_UTF8InEven",
				"testBug545769_UTF8InOdd",
		});
	}

	public ConsoleInputTests(String name) {
		super(name);
	}

    @Override
	protected void setUp() throws Exception {
        super.setUp();
        fStarted = false;
        fStopped = false;
    }

    /**
     * Writes text to the console with line feeds (like pasting multiple lines).
     * The lines with line delimiters should be echoed back. The text remaining
     * on the last line (without a line delimiter) should remain in the input
     * buffer until it is ended with a line delimiter.
     */
	public void testMultiLineInput() throws Exception {
		ConsoleLineTracker.setDelegate(this);
		ILaunchConfiguration configuration = getLaunchConfiguration("ConsoleInput");
		ILaunch launch = null;
		try {
			launch = configuration.launch(ILaunchManager.RUN_MODE, null);
			waitStarted();
			String[] list = appendAndGet(fConsole, "one\ntwo\nexit", 4);
			verifyOutput(new String[]{"one", "two", "exitone", "two"}, list);

			// end the program
			list = appendAndGet(fConsole, "three\n", 3);
			verifyOutput(new String[]{"three", "exitthree", IInternalDebugCoreConstants.EMPTY_STRING}, list);

		} finally {
			ConsoleLineTracker.setDelegate(null);
			launch.getProcesses()[0].terminate();
			getLaunchManager().removeLaunch(launch);
		}
	}

    /**
     * Tests closing standard in
     */
	public void testEOF() throws Exception {
		ConsoleLineTracker.setDelegate(this);
		ILaunchConfiguration configuration = getLaunchConfiguration("ConsoleInput");
		ILaunch launch = null;
		try {
			launch = configuration.launch(ILaunchManager.RUN_MODE, null);
			waitStarted();
			String[] list = appendAndGet(fConsole, "one\ntwo\n", 4);
			verifyOutput(new String[]{"one", "two", "one", "two"}, list);

			// send EOF
			IStreamsProxy streamsProxy = launch.getProcesses()[0].getStreamsProxy();
			assertTrue("should be an IStreamsProxy2", streamsProxy instanceof IStreamsProxy2);
			IStreamsProxy2 proxy2 = (IStreamsProxy2)streamsProxy;
			fLinesRead.clear();
			proxy2.closeInputStream();
			int attempts = 0;
			while (fLinesRead.size() < 2) {
				spinEventLoop();
				synchronized (fLinesRead) {
					if (fLinesRead.size() < 2) {
						fLinesRead.wait(200);
					}
				}
				attempts++;
				if (attempts > 150) {
					break;
				}
			}
			assertEquals("Wrong number of lines", 2, fLinesRead.size());
			assertEquals("Should be EOF message", "EOF", fLinesRead.get(0));
			assertEquals("Should be empty line", IInternalDebugCoreConstants.EMPTY_STRING, fLinesRead.get(1));
		} finally {
			ConsoleLineTracker.setDelegate(null);
			launch.getProcesses()[0].terminate();
			getLaunchManager().removeLaunch(launch);
		}
	}

	private void verifyOutput(String[] expected, String[] actual) {
		for (int i = 0; i < actual.length; i++) {
			assertEquals("Wrong message", expected[i], actual[i]);
		}
	}

	/**
	 * Appends the given text to the given console and waits for the number
	 * of lines to be written to the console. Returns the lines written to
	 * the console.
	 *
	 * @param console
	 * @param text
	 * @param linesExpected
	 * @return lines written to the console without line delimiters
	 * @throws Exception
	 */
	private String[] appendAndGet(IConsole console, final String text, int linesExpected) throws Exception {
		fLinesRead.clear();
		final IDocument document = console.getDocument();
		DebugUIPlugin.getStandardDisplay().asyncExec(new Runnable() {
            @Override
			public void run() {
                try {
                    document.replace(document.getLength(), 0, text);
                } catch (BadLocationException e) {
                    e.printStackTrace();
                }
            }
        });

		int attempts = 0;
		while (fLinesRead.size() < linesExpected) {
			spinEventLoop();
			synchronized (fLinesRead) {
				if (fLinesRead.size() < linesExpected) {
					fLinesRead.wait(200);
				}
			}
			attempts++;
			if (attempts > 150) {
				break;
			}
		}
		assertEquals("Wrong number of lines", linesExpected, fLinesRead.size());
		return fLinesRead.toArray(new String[0]);
	}

	/**
	 * Appends the given text to the given console. Text should not have new lines.
	 *
	 * @param console
	 * @param text
	 * @throws Exception
	 */
	private void append(IConsole console, final String text) throws Exception {
		final IDocument document = console.getDocument();
		DebugUIPlugin.getStandardDisplay().asyncExec(new Runnable() {
            @Override
			public void run() {
                try {
                    document.replace(document.getLength(), 0, text);
                } catch (BadLocationException e) {
                    e.printStackTrace();
                }
            }
        });
		spinEventLoop();
	}

	/**
	 * Deletes all text in the given console.
	 *
	 * @param console
	 * @throws Exception
	 */
	private void deleteAll(IConsole console) throws Exception {
		final IDocument document = console.getDocument();
		DebugUIPlugin.getStandardDisplay().asyncExec(new Runnable() {
            @Override
			public void run() {
                try {
                    document.replace(0, document.getLength(), "");
                } catch (BadLocationException e) {
                    e.printStackTrace();
                }
            }
        });
		spinEventLoop();
	}

	/**
	 * @see org.eclipse.debug.ui.console.IConsoleLineTracker#dispose()
	 */
	@Override
	public void dispose() {
	}

	/**
	 * @see org.eclipse.debug.ui.console.IConsoleLineTracker#init(org.eclipse.debug.ui.console.IConsole)
	 */
	@Override
	public void init(IConsole console) {
		synchronized (fConsoleLock) {
			fConsole = console;
			fStarted = true;
			fConsoleLock.notifyAll();
		}
	}

	/**
	 * @see org.eclipse.debug.ui.console.IConsoleLineTracker#lineAppended(org.eclipse.jface.text.IRegion)
	 */
	@Override
	public void lineAppended(IRegion line) {
		if (fStarted) {
			synchronized (fLinesRead) {
				try {
					String text = fConsole.getDocument().get(line.getOffset(), line.getLength());
					if (!JavaOutputHelpers.isKnownExtraneousOutput(text)) {
						fLinesRead.add(text);
					}
				} catch (BadLocationException e) {
				    e.printStackTrace();
				}
				fLinesRead.notifyAll();
			}
		}
	}

	private void waitStarted() throws InterruptedException {
		synchronized (fConsoleLock) {
			if (!fStarted) {
				fConsoleLock.wait(30000);
			}
		}
		assertNotNull("Console is null", fConsole);
		if (Platform.OS_MACOSX.equals(Platform.getOS())) {
			// on OSX java process writes unexpected message to stderr due to https://bugs.openjdk.java.net/browse/JDK-8022291
			// need to wait for the message to fully appear so it can be filtered in #lineAppended above
			Thread.sleep(1000L);
		}
	}

	/**
	 * @see org.eclipse.debug.ui.console.IConsoleLineTracker#streamClosed()
	 */
	@Override
	public void consoleClosed() {
	    synchronized (fLock) {
			fStopped = true;
			fLock.notifyAll();
        }
	}

	/**
	 * Tests the scenario reported in bug 241394 - 'a', backspace, 'b', backspace, 'c', Enter.
	 * Result should be 'c'.
	 *
	 * @throws Exception
	 */
	public void testDeleteAllEnteredText() throws Exception {
		ConsoleLineTracker.setDelegate(this);
		ILaunchConfiguration configuration = getLaunchConfiguration("ConsoleInput");
		ILaunch launch = null;
		try {
			launch = configuration.launch(ILaunchManager.RUN_MODE, null);
			waitStarted();
			append(fConsole, "a");
			deleteAll(fConsole);
			append(fConsole, "b");
			deleteAll(fConsole);
			String[] list = appendAndGet(fConsole, "c\n", 2);
			verifyOutput(new String[]{"c", "c"}, list);

		} finally {
			ConsoleLineTracker.setDelegate(null);
			launch.getProcesses()[0].terminate();
			getLaunchManager().removeLaunch(launch);
		}
	}

	/**
	 * Test if two byte UTF-8 characters get disrupted on there way to the running process input.
	 * <p>
	 * This test starts every two byte character on an even byte offset.
	 * </p>
	 *
	 * @throws Exception
	 *             if the test gets in trouble
	 */
	public void testBug545769_UTF8InEven() throws Exception {
		// 4200 characters result in 8400 bytes which should be more than most common buffer sizes.
		utf8InputTest("", 4200);
	}

	/**
	 * Test if two byte UTF-8 characters get disrupted on there way to the running process input.
	 * <p>
	 * This test starts every two byte character on an odd byte offset.
	 * </p>
	 *
	 * @throws Exception
	 *             if the test gets in trouble
	 */
	public void testBug545769_UTF8InOdd() throws Exception {
		// 4200 characters result in 8400 bytes which should be more than most common buffer sizes.
		utf8InputTest(">", 4200);
	}

	/**
	 * Shared code for the UTF-8 input tests.
	 * <p>
	 * Send some two byte UTF-8 characters to process and read the echo back.
	 * </p>
	 *
	 * @param prefix
	 *            an arbitrary prefix inserted before the two byte UTF-8 characters. Used to move the other characters to specific offsets e.g. a
	 *            prefix of one byte will produce an input string where every two byte character starts at an odd offset.
	 * @param numTwoByteCharacters
	 *            number of two byte UTF-8 characters to send to process
	 * @throws Exception
	 *             if the test gets in trouble
	 */
	private void utf8InputTest(String prefix, int numTwoByteCharacters) throws Exception {
		ConsoleLineTracker.setDelegate(this);
		ILaunchConfiguration configuration = getLaunchConfiguration("ConsoleInput");
		ILaunchConfigurationWorkingCopy configurationCopy = configuration.getWorkingCopy();
		configurationCopy.setAttribute(DebugPlugin.ATTR_CONSOLE_ENCODING, StandardCharsets.UTF_8.name());
		ILaunch launch = null;
		try {
			launch = configurationCopy.launch(ILaunchManager.RUN_MODE, null);
			String input = prefix + String.join("", Collections.nCopies(numTwoByteCharacters, "\u00F8"));
			waitStarted();
			String[] list = appendAndGet(fConsole, input + "\n", 2);
			verifyOutput(new String[] { input, input }, list);

		} finally {
			ConsoleLineTracker.setDelegate(null);
			launch.getProcesses()[0].terminate();
			getLaunchManager().removeLaunch(launch);
		}
	}

	private void spinEventLoop() {
		final Display display= DebugUIPlugin.getStandardDisplay();
		Runnable runnable= new Runnable() {
			@Override
			public void run() {
				while (display.readAndDispatch()) {
				}
			}
		};
		if (Display.getCurrent() == display) {
			runnable.run();
		} else {
			display.syncExec(runnable);
		}
	}
}
