/*******************************************************************************
 * Copyright (c) 2000, 2018 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.internal.ui.text.java.hover;

import java.io.IOException;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;

import org.eclipse.core.runtime.CoreException;

import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextViewer;

import org.eclipse.ui.IEditorPart;
import org.eclipse.ui.part.IWorkbenchPartOrientation;

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

import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.ISourceReference;
import org.eclipse.jdt.core.ITypeParameter;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.Javadoc;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.manipulation.SharedASTProviderCore;

import org.eclipse.jdt.internal.core.manipulation.StubUtility;
import org.eclipse.jdt.internal.core.manipulation.util.Strings;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.TokenScanner;
import org.eclipse.jdt.internal.corext.util.Messages;

import org.eclipse.jdt.internal.ui.JavaPlugin;
import org.eclipse.jdt.internal.ui.javaeditor.JavaEditor;
import org.eclipse.jdt.internal.ui.javaeditor.JavaSourceViewer;
import org.eclipse.jdt.internal.ui.text.JavaCodeReader;
import org.eclipse.jdt.internal.ui.text.JavaPairMatcher;


/**
 * Provides as hover info the source of the selected JavaElement, or the source near the matching
 * opening curly brace.
 */
public class JavaSourceHover extends AbstractJavaEditorTextHover {

	/**
	 * The upward shift in location in lines for the bracket hover.
	 *
	 * @since 3.8
	 */
	private int fUpwardShiftInLines;

	/**
	 * The status text for the bracket hover.
	 *
	 * @since 3.8
	 */
	private String fBracketHoverStatus;

	/**
	 * The hovered Java element to get the source.
	 * 
	 * @since 3.14
	 */
	private IJavaElement fJavaElement;

	class JavaSourceInformationInput {
		private IJavaElement fElement;

		private String fHoverInfo;

		public JavaSourceInformationInput(IJavaElement javaElement, String hoverInfo) {
			fElement= javaElement;
			fHoverInfo= hoverInfo;
		}

		public IJavaElement getJavaElement() {
			return fElement;
		}

		public String getHoverInfo() {
			return fHoverInfo;
		}
	}

	@Override
	public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) {
		String hoverInfoString= getHoverInfo(textViewer, hoverRegion);
		if (hoverInfoString == null) {
			return null;
		}
		if (fJavaElement == null) {
			return hoverInfoString;
		}
		return new JavaSourceInformationInput(fJavaElement, hoverInfoString);
	}

	@Override
	@Deprecated
	public String getHoverInfo(ITextViewer textViewer, IRegion region) {
		IJavaElement[] result= getJavaElementsAt(textViewer, region);
		fJavaElement= null;

		fUpwardShiftInLines= 0;
		fBracketHoverStatus= null;

		if (result == null || result.length == 0) {
			return getBracketHoverInfo(textViewer, region);
		}

		if (result.length > 1)
			return null;

		fJavaElement= result[0];
		if ((fJavaElement instanceof IMember || fJavaElement instanceof ILocalVariable || fJavaElement instanceof ITypeParameter) && fJavaElement instanceof ISourceReference) {
			try {
				String source= ((ISourceReference) fJavaElement).getSource();

				String[] sourceLines= getTrimmedSource(source, fJavaElement);
				if (sourceLines == null)
					return null;

				String delim= StubUtility.getLineDelimiterUsed(fJavaElement);
				source= Strings.concatenate(sourceLines, delim);

				return source;
			} catch (JavaModelException ex) {
				//do nothing
			}
		}
		return null;
	}

	private String getBracketHoverInfo(final ITextViewer textViewer, IRegion region) {
		boolean isElsePart= false;
		IEditorPart editor= getEditor();
		ITypeRoot editorInput= getEditorInputJavaElement();
		if (!(editor instanceof JavaEditor) || editorInput == null) {
			return null;
		}

		int offset= region.getOffset();
		IDocument document= textViewer.getDocument();
		if (document == null)
			return null;
		try {
			char c= document.getChar(offset);
			if (c != '}')
				return null;
			JavaPairMatcher matcher= ((JavaEditor) editor).getBracketMatcher();
			if (matcher == null)
				return null;
			IRegion match= matcher.match(document, offset);
			if (match == null)
				return null;

			String delim= StubUtility.getLineDelimiterUsed(editorInput);

			CompilationUnit ast= SharedASTProviderCore.getAST(editorInput, SharedASTProviderCore.WAIT_NO, null);
			if (ast == null)
				return null;
			ASTNode bracketNode= NodeFinder.perform(ast, match.getOffset(),
					match.getLength());
			if (bracketNode == null)
				return null;
			ASTNode node;
			ASTNode parent= bracketNode.getParent();
			if (parent instanceof IfStatement) {
				IfStatement parentIfStmt= (IfStatement) parent;
				if ((parentIfStmt.getElseStatement() != null && ASTNodes.getInclusiveEnd(parentIfStmt.getElseStatement()) == offset) // if [else if]* else
						|| (parentIfStmt.getLocationInParent() == IfStatement.ELSE_STATEMENT_PROPERTY && ASTNodes.getInclusiveEnd(parentIfStmt.getThenStatement()) == offset)) { // if [else if]+ else?
					isElsePart= true;
					while (parent.getLocationInParent() == IfStatement.ELSE_STATEMENT_PROPERTY) {
						parent= parent.getParent();
					}
				}
			}
			if (bracketNode instanceof Block && !(parent instanceof Block) && !(parent instanceof SwitchStatement)) {
				node= parent;
			} else {
				node= bracketNode;
			}
			int nodeStart;
			int nodeLength;
			if (node instanceof BodyDeclaration) {
				BodyDeclaration declaration= (BodyDeclaration) node;
				Javadoc javadoc= declaration.getJavadoc();
				int lengthOfJavadoc= javadoc == null ? 0 : javadoc.getLength() +
						delim.length();
				nodeStart= node.getStartPosition() + lengthOfJavadoc;
				nodeLength= node.getLength() - lengthOfJavadoc;
			} else {
				nodeStart= node.getStartPosition();
				nodeLength= ASTNodes.getExclusiveEnd(bracketNode) - nodeStart;
			}

			int line1= document.getLineOfOffset(nodeStart);
			int sourceOffset= document.getLineOffset(line1);
			int line2= document.getLineOfOffset(nodeStart + nodeLength);
			int hoveredLine= document.getLineOfOffset(offset);
			if (line2 > hoveredLine)
				line2= hoveredLine;

			//check if line1 is visible
			final int[] topIndex= new int[1];
			StyledText textWidget= textViewer.getTextWidget();
			if (textWidget == null)
				return null;

			Display display;
			try {
				display= textWidget.getDisplay();
			} catch (SWTException ex) {
				if (ex.code == SWT.ERROR_WIDGET_DISPOSED)
					return null;
				else
					throw ex;
			}

			display.syncExec(new Runnable() {
				@Override
				public void run() {
					topIndex[0]= textViewer.getTopIndex();
				}
			});

			int topLine= topIndex[0];
			if (topLine == -1)
				return null;
			int noOfSourceLines;
			IRegion endLine;
			int skippedLines= 0;
			int wLine1= ((JavaSourceViewer) textViewer).modelLine2WidgetLine(line1);
			int wLine2= ((JavaSourceViewer) textViewer).modelLine2WidgetLine(line2);
			if ((line1 < topLine) || (wLine1 != -1 && (wLine2 - wLine1 != line2 - line1))) {
				// match not visible or content is folded - see bug 399997
				if (isElsePart) {
					return getBracketHoverInfo((IfStatement) node, bracketNode, document, editorInput, delim); // see bug 377141, 201850
				}
				noOfSourceLines= 3;
				if ((line2 - line1) < noOfSourceLines) {
					noOfSourceLines= line2 - line1;
				}
				skippedLines= Math.abs(line2 - line1 - noOfSourceLines);
				if (skippedLines == 1) {
					noOfSourceLines++;
					skippedLines= 0;
				}
				endLine= document.getLineInformation(line1 + noOfSourceLines);
				fUpwardShiftInLines= noOfSourceLines;
				if (skippedLines > 0) {
					fBracketHoverStatus= Messages.format(JavaHoverMessages.JavaSourceHover_skippedLines, Integer.valueOf(skippedLines));
				}
			} else {
				noOfSourceLines= line2 - line1;
				endLine= document.getLineInformation(line2);
				fUpwardShiftInLines= line2 - line1;
			}
			if (fUpwardShiftInLines == 0)
				return null;

			int sourceLength= (endLine.getOffset() + endLine.getLength()) - sourceOffset;
			String source= document.get(sourceOffset, sourceLength);
			String[] sourceLines= getTrimmedSource(source, editorInput);
			if (sourceLines == null)
				return null;
			String[] str= new String[noOfSourceLines];
			System.arraycopy(sourceLines, 0, str, 0, noOfSourceLines);
			source= Strings.concatenate(str, delim);
			if (skippedLines > 0) {
				source= source.concat(delim).concat(JavaHoverMessages.JavaSourceHover_skippedLinesSymbol);
				fUpwardShiftInLines++;
			}
			return source;
		} catch (BadLocationException e) {
			JavaPlugin.log(e);
			return null;
		}
	}

	/**
	 * Creates the hover text for 'else if' or 'else' closing bracket in 'if [else if]+ else?' or
	 * 'if [else if]* else' cases by stitching together all the headers when the beginning of the
	 * first 'if' is not visible in the text editor.
	 *
	 * @param ifNode the first 'if' node in the structure
	 * @param bracketNode the node at whose closing bracket the hover text is required
	 * @param document the input document of the text viewer on which the hover popup should be
	 *            shown
	 * @param editorInput the editor's input as {@link ITypeRoot}
	 * @param delim the line delimiter used for the editorInput
	 * @return the hover text for 'else if' or 'else' closing bracket in 'if [else if]+ else?' or
	 *         'if [else if]* else' cases respectively
	 * @throws BadLocationException if an attempt has been performed to access a non-existing
	 *             position in the document
	 * @since 3.9
	 */
	private String getBracketHoverInfo(IfStatement ifNode, ASTNode bracketNode, final IDocument document, final ITypeRoot editorInput, final String delim) throws BadLocationException {
		int totalSkippedLines= 0;
		String hoverText= null;

		Statement currentStatement= ifNode.getThenStatement();
		int nodeStart= ifNode.getStartPosition();
		while (currentStatement != null) {
			int nodeLength= ASTNodes.getExclusiveEnd(currentStatement) - nodeStart;
			int line1= document.getLineOfOffset(nodeStart);
			int sourceOffset= document.getLineOffset(line1);
			int line2= document.getLineOfOffset(nodeStart + nodeLength);
			int line3= line2;
			if (currentStatement != bracketNode && ifNode != null && ifNode.getElseStatement() != null) {
				int elseStartOffset= getNextElseOffset(ifNode.getThenStatement(), editorInput);
				if (elseStartOffset != -1) {
					line3= document.getLineOfOffset(elseStartOffset); // next 'else'
				}
			}
			int noOfTotalLines= (line2 == line3) ? (line2 - line1) : (line2 - line1 + 1);
			int noOfSourceLines= 3;

			if (noOfTotalLines < noOfSourceLines) {
				noOfSourceLines= noOfTotalLines;
			}
			int noOfSkippedLines= noOfTotalLines - noOfSourceLines;
			if (noOfSkippedLines == 1) {
				noOfSourceLines++;
				noOfSkippedLines= 0;
			}

			if (noOfSourceLines > 0) {
				IRegion endLine= document.getLineInformation(line1 + noOfSourceLines - 1);
				int sourceLength= (endLine.getOffset() + endLine.getLength()) - sourceOffset;
				String source= document.get(sourceOffset, sourceLength);
				String[] sourceLines= getTrimmedSource(source, editorInput);
				if (sourceLines == null)
					return null;
				source= Strings.concatenate(sourceLines, delim);
				if (noOfSkippedLines > 0) {
					source= source.concat(delim).concat(JavaHoverMessages.JavaSourceHover_skippedLinesSymbol);
					fUpwardShiftInLines++;
				}

				fUpwardShiftInLines+= noOfSourceLines;
				totalSkippedLines+= noOfSkippedLines;
				if (hoverText == null) {
					hoverText= source;
				} else {
					hoverText= hoverText.concat(delim).concat(source);
				}
			}
			// advance currentStatement to the next 'else if' or 'else' statement; set it to null when no further processing is required
			// advance ifNode to the 'if' in next 'else if'; set it to null if 'else' is reached
			if (currentStatement != bracketNode) {
				Statement thenStatement= ifNode.getThenStatement();
				Statement nextStatement= ifNode.getElseStatement();
				if (nextStatement instanceof IfStatement) {
					currentStatement= ((IfStatement) nextStatement).getThenStatement();
					ifNode= (IfStatement) nextStatement;
				} else {
					currentStatement= nextStatement;
					ifNode= null;
				}
				// update nodeStart to next 'else' start offset
				int nextStartOffset= getNextElseOffset(thenStatement, editorInput);
				if (nextStartOffset != -1) {
					nodeStart= nextStartOffset;
				} else {
					nodeStart= nextStatement.getStartPosition();
				}
			} else {
				currentStatement= null;
			}
		}

		if (fUpwardShiftInLines == 0)
			return null;
		if ((totalSkippedLines) > 0) {
			fBracketHoverStatus= Messages.format(JavaHoverMessages.JavaSourceHover_skippedLines, Integer.valueOf(totalSkippedLines));
		}
		return hoverText;
	}

	private int getNextElseOffset(Statement then, ITypeRoot editorInput) {
		int thenEnd= ASTNodes.getExclusiveEnd(then);
		try {
			TokenScanner scanner= new TokenScanner(editorInput);
			return scanner.getNextStartOffset(thenEnd, true);
		} catch (CoreException e) {
			// ignore
		}
		return -1;
	}

	/**
	 * Returns the trimmed source lines.
	 *
	 * @param source the source string, could be <code>null</code>
	 * @param javaElement the java element
	 * @return the trimmed source lines or <code>null</code>
	 */
	private String[] getTrimmedSource(String source, IJavaElement javaElement) {
		if (source == null)
			return null;
		source= removeLeadingComments(source);
		String[] sourceLines= Strings.convertIntoLines(source);
		Strings.trimIndentation(sourceLines, javaElement.getJavaProject());
		return sourceLines;
	}

	private String removeLeadingComments(String source) {
		final JavaCodeReader reader= new JavaCodeReader();
		IDocument document= new Document(source);
		int i;
		try {
			reader.configureForwardReader(document, 0, document.getLength(), true, false);
			int c= reader.read();
			while (c != -1 && (c == '\r' || c == '\n')) {
				c= reader.read();
			}
			i= reader.getOffset();
			reader.close();
		} catch (IOException ex) {
			i= 0;
		} finally {
			try {
				reader.close();
			} catch (IOException ex) {
				JavaPlugin.log(ex);
			}
		}

		if (i < 0)
			return source;
		return source.substring(i);
	}

	/*
	 * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
	 * @since 3.0
	 */
	@Override
	public IInformationControlCreator getHoverControlCreator() {
		if (fUpwardShiftInLines > 0)
			return createInformationControlCreator(false, fBracketHoverStatus, true);
		else
			return createInformationControlCreator(false, EditorsUI.getTooltipAffordanceString(), true);
	}

	/*
	 * @see org.eclipse.jdt.internal.ui.text.java.hover.AbstractJavaEditorTextHover#getInformationPresenterControlCreator()
	 * @since 3.0
	 */
	@Override
	public IInformationControlCreator getInformationPresenterControlCreator() {
		if (fUpwardShiftInLines > 0)
			return createInformationControlCreator(false, fBracketHoverStatus, true);
		else
			return createInformationControlCreator(true, EditorsUI.getTooltipAffordanceString(), true);
	}

	/**
	 * Returns the information control creator.
	 *
	 * @param isResizable <code>true</code> if resizable
	 * @param statusFieldText the text to be used in the optional status field or <code>null</code>
	 *            if the status field should be hidden
	 * @param doShiftUp <code>true</code> iff {@link #fUpwardShiftInLines} should be considered
	 * @return the information control creator
	 * @since 3.8
	 */
	private IInformationControlCreator createInformationControlCreator(final boolean isResizable, final String statusFieldText, final boolean doShiftUp) {
		return new IInformationControlCreator() {
			@Override
			public IInformationControl createInformationControl(final Shell parent) {
				final IEditorPart editor= getEditor();
				int orientation= SWT.NONE;
				if (editor instanceof IWorkbenchPartOrientation)
					orientation= ((IWorkbenchPartOrientation) editor).getOrientation();

				return new SourceViewerInformationControl(parent, isResizable, orientation, statusFieldText) {
					@Override
					public void setLocation(Point location) {
						Point loc= location;
						if (doShiftUp && fUpwardShiftInLines > 0) {
							Point size= super.computeSizeConstraints(0, fUpwardShiftInLines + 1);
							//bracket hover is rendered above '}'
							int y= location.y - size.y - 5; //AbstractInformationControlManager.fMarginY = 5
							Rectangle trim= computeTrim();
							loc= new Point(location.x + trim.x - getViewer().getTextWidget().getLeftMargin(), y - trim.height - trim.y);
						}
						super.setLocation(loc);
					}

					@Override
					public Point computeSizeConstraints(int widthInChars, int heightInChars) {
						if (doShiftUp && fUpwardShiftInLines > 0) {
							Point sizeConstraints= super.computeSizeConstraints(widthInChars, heightInChars);
							return new Point(sizeConstraints.x, 0); //set height as 0 to ensure selection of bottom anchor in AbstractInformationControlManager.computeInformationControlLocation(...)
						} else {
							return super.computeSizeConstraints(widthInChars, heightInChars);
						}
					}

					@Override
					public void setSize(int width, int height) {
						if (doShiftUp && fUpwardShiftInLines != 0) {
							//compute the correct height of hover, this was set to 0 in computeSizeConstraints(..)
							Point size= super.computeSizeConstraints(0, fUpwardShiftInLines);
							Rectangle trim= computeTrim();
							super.setSize(width, size.y + trim.height - trim.y);
						} else {
							super.setSize(width, height);
						}
					}

					@Override
					public IInformationControlCreator getInformationPresenterControlCreator() {
						if (doShiftUp && fUpwardShiftInLines > 0) {
							// Hack: We don't wan't to have auto-enrichment when the mouse moves into the hover,
							// but we do want F2 to persist the hover. The framework has no way to distinguish the
							// two requests, so we have to implement this aspect.
							for (StackTraceElement element : Thread.currentThread().getStackTrace()) {
								if ("canMoveIntoInformationControl".equals(element.getMethodName()) //$NON-NLS-1$
										&& "org.eclipse.jface.text.AbstractHoverInformationControlManager".equals(element.getClassName())) //$NON-NLS-1$
									return null; //do not enrich bracket hover
							}
							return JavaSourceHover.this.createInformationControlCreator(isResizable && !isResizable, statusFieldText, false);
						} else {
							return super.getInformationPresenterControlCreator();
						}
					}
				};
			}
		};
	}
}
