/*******************************************************************************
 * Copyright (c) 2000, 2020 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
 *      Bug Menot - Bug 445867
 *******************************************************************************/
package org.eclipse.jdt.internal.debug.ui;


import java.util.Optional;
import java.util.StringJoiner;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;

import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IAdaptable;
import org.eclipse.debug.core.DebugEvent;
import org.eclipse.debug.core.DebugException;
import org.eclipse.debug.core.model.IVariable;
import org.eclipse.debug.ui.DebugUITools;
import org.eclipse.debug.ui.IDebugUIConstants;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.IClassFile;
import org.eclipse.jdt.core.ICodeAssist;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IInitializer;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.ILocalVariable;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.ITypeRoot;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTParser;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.NodeFinder;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
import org.eclipse.jdt.core.dom.ThisExpression;
import org.eclipse.jdt.core.manipulation.SharedASTProviderCore;
import org.eclipse.jdt.debug.core.IJavaDebugTarget;
import org.eclipse.jdt.debug.core.IJavaObject;
import org.eclipse.jdt.debug.core.IJavaReferenceType;
import org.eclipse.jdt.debug.core.IJavaStackFrame;
import org.eclipse.jdt.debug.core.IJavaThread;
import org.eclipse.jdt.debug.core.IJavaType;
import org.eclipse.jdt.debug.core.IJavaValue;
import org.eclipse.jdt.debug.core.IJavaVariable;
import org.eclipse.jdt.debug.eval.IAstEvaluationEngine;
import org.eclipse.jdt.debug.eval.IEvaluationListener;
import org.eclipse.jdt.debug.eval.IEvaluationResult;
import org.eclipse.jdt.internal.debug.core.JDIDebugPlugin;
import org.eclipse.jdt.internal.debug.core.logicalstructures.JDIPlaceholderVariable;
import org.eclipse.jdt.internal.debug.eval.ast.engine.ASTEvaluationEngine;
import org.eclipse.jdt.ui.JavaUI;
import org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.ITextHoverExtension;
import org.eclipse.jface.text.ITextHoverExtension2;
import org.eclipse.jface.text.ITextViewer;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IEditorPart;


public class JavaDebugHover implements IJavaEditorTextHover, ITextHoverExtension, ITextHoverExtension2 {

    private IEditorPart fEditor;

	/* (non-Javadoc)
	 * @see org.eclipse.jdt.ui.text.java.hover.IJavaEditorTextHover#setEditor(org.eclipse.ui.IEditorPart)
	 */
	@Override
	public void setEditor(IEditorPart editor) {
	    fEditor = editor;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.ITextHover#getHoverRegion(org.eclipse.jface.text.ITextViewer, int)
	 */
	@Override
	public IRegion getHoverRegion(ITextViewer textViewer, int offset) {
		return JavaWordFinder.findWord(textViewer.getDocument(), offset);
	}

	/**
	 * Returns the stack frame in which to search for variables, or <code>null</code>
	 * if none.
	 *
	 * @return the stack frame in which to search for variables, or <code>null</code>
	 * if none
	 */
	protected IJavaStackFrame getFrame() {
	    IAdaptable adaptable = DebugUITools.getDebugContext();
		if (adaptable != null) {
			return adaptable.getAdapter(IJavaStackFrame.class);
		}
		return null;
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.ITextHover#getHoverInfo(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
	 */
	@Override
	public String getHoverInfo(ITextViewer textViewer, IRegion hoverRegion) {
		Object object = getHoverInfo2(textViewer, hoverRegion);
		if (object instanceof IVariable) {
			IVariable var = (IVariable) object;
			return getVariableText(var);
		}
		return null;
	}

	/**
	 * Returns a local variable in the given frame based on the hover region
	 * or <code>null</code> if none.
	 *
	 * @return local variable or <code>null</code>
	 */
	private IVariable resolveLocalVariable(IJavaStackFrame frame, ITextViewer textViewer, IRegion hoverRegion) {
		if (frame != null) {
			try {
				IDocument document= textViewer.getDocument();
				if (document != null) {
					String variableName= document.get(hoverRegion.getOffset(), hoverRegion.getLength());
					return findLocalVariable(frame, variableName);
				}
			} catch (BadLocationException x) {
			}
		}
		return null;
	}

	/**
	 * Returns a local variable in the given frame based on the the given name
	 * or <code>null</code> if none.
	 *
	 * @return local variable or <code>null</code>
	 */
	public static IVariable findLocalVariable(IJavaStackFrame frame, String variableName) {
		if (frame != null) {
			try {
				return frame.findVariable(variableName);
			} catch (DebugException x) {
				if (x.getStatus().getCode() != IJavaThread.ERR_THREAD_NOT_SUSPENDED) {
					JDIDebugUIPlugin.log(x);
				}
			}
		}
		return null;
	}

	/**
	 * Returns HTML text for the given variable
	 */
	private static String getVariableText(IVariable variable) {
	    StringBuilder buffer= new StringBuilder();
		JDIModelPresentation modelPresentation = getModelPresentation();
		buffer.append("<p><pre>"); //$NON-NLS-1$
		String variableText= modelPresentation.getVariableText((IJavaVariable) variable);
		buffer.append(replaceHTMLChars(variableText));
		buffer.append("</pre></p>"); //$NON-NLS-1$
		modelPresentation.dispose();
		if (buffer.length() > 0) {
			return buffer.toString();
		}
		return null;
	}

	/**
	 * Replaces reserved HTML characters in the given string with
	 * their escaped equivalents. This is to ensure that variable
	 * values containing reserved characters are correctly displayed.
     */
    private static String replaceHTMLChars(String variableText) {
        StringBuilder buffer= new StringBuilder(variableText.length());
        char[] characters = variableText.toCharArray();
        for (int i = 0; i < characters.length; i++) {
            char character= characters[i];
            switch (character) {
            	case '<':
            	    buffer.append("&lt;"); //$NON-NLS-1$
            	    break;
            	case '>':
            	    buffer.append("&gt;"); //$NON-NLS-1$
            	    break;
            	case '&':
            	    buffer.append("&amp;"); //$NON-NLS-1$
            	    break;
            	case '"':
            	    buffer.append("&quot;"); //$NON-NLS-1$
            	    break;
            	default:
            	    buffer.append(character);
            }
        }
        return buffer.toString();
    }

    /**
	 * Returns a configured model presentation for use displaying variables.
	 */
	private static JDIModelPresentation getModelPresentation() {
		JDIModelPresentation presentation = new JDIModelPresentation();

		String[][] booleanPrefs= {
				{IJDIPreferencesConstants.PREF_SHOW_QUALIFIED_NAMES, JDIModelPresentation.DISPLAY_QUALIFIED_NAMES}};
	    String viewId= IDebugUIConstants.ID_VARIABLE_VIEW;
	    for (int i = 0; i < booleanPrefs.length; i++) {
	    	boolean preferenceValue = getBooleanPreferenceValue(viewId, booleanPrefs[i][0]);
			presentation.setAttribute(booleanPrefs[i][1], (preferenceValue ? Boolean.TRUE : Boolean.FALSE));
		}
		return presentation;
	}

	   /**
     * Returns the value of this filters preference (on/off) for the given
     * view.
     *
     * @param part
     * @return boolean
     */
    public static boolean getBooleanPreferenceValue(String id, String preference) {
        String compositeKey = id + "." + preference; //$NON-NLS-1$
        IPreferenceStore store = JDIDebugUIPlugin.getDefault().getPreferenceStore();
        boolean value = false;
        if (store.contains(compositeKey)) {
            value = store.getBoolean(compositeKey);
        } else {
            value = store.getBoolean(preference);
        }
        return value;
    }

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.ITextHoverExtension#getHoverControlCreator()
	 */
	@Override
	public IInformationControlCreator getHoverControlCreator() {
		return new ExpressionInformationControlCreator();
	}

	/* (non-Javadoc)
	 * @see org.eclipse.jface.text.ITextHoverExtension2#getHoverInfo2(org.eclipse.jface.text.ITextViewer, org.eclipse.jface.text.IRegion)
	 */
	@Override
	public Object getHoverInfo2(ITextViewer textViewer, IRegion hoverRegion) {
	    IJavaStackFrame frame = getFrame();
	    if (frame != null) {
	        // first check for 'this' - code resolve does not resolve java elements for 'this'
	        IDocument document= textViewer.getDocument();
			if (document != null) {
			    try {
                    String variableName= document.get(hoverRegion.getOffset(), hoverRegion.getLength());
                    if (variableName.equals("this")) { //$NON-NLS-1$
                        try {
                            IJavaVariable variable = frame.findVariable(variableName);
                            if (variable != null) {
                                return variable;
                            }
                        } catch (DebugException e) {
                            return null;
                        }
                    }
                } catch (BadLocationException e) {
                    return null;
                }
			}
		    ICodeAssist codeAssist = null;
		    if (fEditor != null) {
				IEditorInput input = fEditor.getEditorInput();
				Object element = JavaUI.getWorkingCopyManager().getWorkingCopy(input);
				if (element == null) {
					element = input.getAdapter(IClassFile.class);
				}
				if (element instanceof ICodeAssist) {
					codeAssist = ((ICodeAssist)element);
				}
		    }
		    if (codeAssist == null) {
		        return resolveLocalVariable(frame, textViewer, hoverRegion);
		    }

			IJavaElement[] resolve = resolveElement(hoverRegion.getOffset(), codeAssist);
			try {
				boolean onArrayLength = false;
				if (resolve.length == 0 && isOverNameLength(hoverRegion, document)) {
					// lets check if this is part of an array variable by jumping 2 chars backward from offset.
					resolve = resolveElement(hoverRegion.getOffset() - 2, codeAssist);
					onArrayLength = (resolve.length == 1) && isLocalOrMemberVariable(resolve[0])
							&& isArrayTypeVariable(resolve[0]);
				}

				for (int i = 0; i < resolve.length; i++) {
					IJavaElement javaElement = resolve[i];
					if (javaElement instanceof IField) {
						IField field = (IField) javaElement;
						IJavaVariable variable = null;
						IJavaDebugTarget debugTarget = (IJavaDebugTarget) frame.getDebugTarget();
						if (Flags.isStatic(field.getFlags()) && !onArrayLength) {
							IJavaType[] javaTypes = debugTarget.getJavaTypes(field.getDeclaringType().getFullyQualifiedName());
            		    	if (javaTypes != null) {
	            		    	for (int j = 0; j < javaTypes.length; j++) {
									IJavaType type = javaTypes[j];
									if (type instanceof IJavaReferenceType) {
										IJavaReferenceType referenceType = (IJavaReferenceType) type;
										variable = referenceType.getField(field.getElementName());
									}
									if (variable != null) {
										break;
									}
								}
            		    	}
            		    	if (variable == null) {
            		    		// the class is not loaded yet, but may be an in-lined primitive constant
            		    		Object constant = field.getConstant();
								if (constant != null) {
									IJavaValue value = null;
            		    			if (constant instanceof Integer) {
										value = debugTarget.newValue(((Integer)constant).intValue());
									} else if (constant instanceof Byte) {
										value = debugTarget.newValue(((Byte)constant).byteValue());
									} else if (constant instanceof Boolean) {
										value = debugTarget.newValue(((Boolean)constant).booleanValue());
									} else if (constant instanceof Character) {
										value = debugTarget.newValue(((Character)constant).charValue());
									} else if (constant instanceof Double) {
										value = debugTarget.newValue(((Double)constant).doubleValue());
									} else if (constant instanceof Float) {
										value = debugTarget.newValue(((Float)constant).floatValue());
									} else if (constant instanceof Long) {
										value = debugTarget.newValue(((Long)constant).longValue());
									} else if (constant instanceof Short) {
										value = debugTarget.newValue(((Short)constant).shortValue());
									} else if (constant instanceof String) {
										value = debugTarget.newValue((String)constant);
									}
            		    			if (value != null) {
            		    				variable = new JDIPlaceholderVariable(field.getElementName(), value);
            		    			}
            		    		}
								if (variable == null) {
									return null; // class not loaded yet and not a constant
								}
            		    	}
            		    } else {
							if ((!frame.isStatic() || isLocalOrMemberVariable(javaElement)) && !frame.isNative()) {
								// we resolve chain elements which are either on "this" or local variables. In case of
								// local variables we also consider static frames.
								if (!(codeAssist instanceof ITypeRoot)) {
									return null;
								}
								ITypeRoot typeRoot = (ITypeRoot) codeAssist;
								ASTNode node = findNodeAtRegion(typeRoot, hoverRegion);
								if (node == null) {
									return null;
								}
								StructuralPropertyDescriptor locationInParent = node.getLocationInParent();
								if (locationInParent == FieldAccess.NAME_PROPERTY) {
									FieldAccess fieldAccess = (FieldAccess) node.getParent();
									if (fieldAccess.getExpression() instanceof ThisExpression) {
										variable = evaluateField(frame, field);
									} else {
										variable = evaluateQualifiedNode(fieldAccess, frame, typeRoot.getJavaProject());
									}
								} else if (locationInParent == QualifiedName.NAME_PROPERTY) {
									variable = evaluateQualifiedNode(node.getParent(), frame, typeRoot.getJavaProject());
								} else {
									variable = evaluateField(frame, field);
								}
            		    	}
            		    }
            		    if (variable != null) {
            		        return variable;
            		    }
            			break;
            		}
            		if (javaElement instanceof ILocalVariable) {
						// if we are on a array, regardless where we are send it to evaluation engine
						if (onArrayLength) {
							if (!(codeAssist instanceof ITypeRoot)) {
								return null;
							}
							ITypeRoot typeRoot = (ITypeRoot) codeAssist;
							ASTNode node = findNodeAtRegion(typeRoot, hoverRegion);
							if (node == null) {
								return null;
							}
							return evaluateQualifiedNode(node.getParent(), frame, typeRoot.getJavaProject());
						}

            		    ILocalVariable var = (ILocalVariable)javaElement;
            		    IJavaElement parent = var.getParent();
						while (!(parent instanceof IMethod) && !(parent instanceof IInitializer) && parent != null) {
            		    	parent = parent.getParent();
            		    }
						if (parent instanceof IInitializer && "()V".equals(frame.getSignature()) //$NON-NLS-1$
								&& "<clinit>".equals(frame.getMethodName())) { //$NON-NLS-1$
							return findLocalVariable(frame, var.getElementName());
						}
            		    if (parent instanceof IMethod) {
            				IMethod method = (IMethod) parent;
            				boolean equal = false;
            				if (method.isBinary()) {
            					// compare resolved signatures
								if (method.getSignature().equals(frame.getSignature()) && method.getElementName().equals(frame.getMethodName())) {
            						equal = true;
								} else {
									// Check if there are variables captured by lambda, see bug 516278
									if (org.eclipse.jdt.internal.debug.core.model.LambdaUtils.isLambdaFrame(frame)) {
										return LambdaUtils.findLocalVariableFromLambdaScope(frame, var);
									}
            					}
            				} else {
            					// compare unresolved signatures

            					// Frames in classes with generics have declaringTypeName like class<V>
            					// We must get rid of this '<V>' for proper comparison
            					String frameDeclaringTypeName = frame.getDeclaringTypeName();
            					int genericPartOffset = frameDeclaringTypeName.indexOf('<');
            					if (genericPartOffset != -1) {
            						frameDeclaringTypeName = frameDeclaringTypeName.substring(0, genericPartOffset);
            					}

            					if (((frame.isConstructor() && method.isConstructor()) || frame.getMethodName().equals(method.getElementName()))
            							&& frameDeclaringTypeName.endsWith(method.getDeclaringType().getElementName())
            							&& frame.getArgumentTypeNames().size() == method.getNumberOfParameters()) {
            						equal = true;
            					}
            					else { // Finding variables in anonymous class
									int index = frame.getDeclaringTypeName().indexOf('$');
									if (index > 0) {
										String name = frame.getDeclaringTypeName().substring(index + 1);
										try {
											Integer.getInteger(name);
											return findLocalVariable(frame, ASTEvaluationEngine.ANONYMOUS_VAR_PREFIX + var.getElementName());
										}
										catch (NumberFormatException ex) {
										}
									} else {
										// Check if there are variables captured by lambda, see bug 516278
										if (org.eclipse.jdt.internal.debug.core.model.LambdaUtils.isLambdaFrame(frame)) {
											return LambdaUtils.findLocalVariableFromLambdaScope(frame, var);
										}
									}
								}
            				}
            				// find variable if equal or method is a Lambda Method
            				if (equal || method.isLambdaMethod()) {
            					return findLocalVariable(frame, var.getElementName());
            				}
            			}
            		    break;
            		}
            	}
            } catch (CoreException e) {
            	JDIDebugPlugin.log(e);
            }
	    }
	    return null;
	}

	private ASTNode findNodeAtRegion(ITypeRoot typeRoot, IRegion hoverRegion) {
		ASTNode root = SharedASTProviderCore.getAST(typeRoot, SharedASTProviderCore.WAIT_NO, null);
		if (root == null) {
			ASTParser parser = ASTParser.newParser(AST.JLS15);
			parser.setSource(typeRoot);
			parser.setFocalPosition(hoverRegion.getOffset());
			root = parser.createAST(null);
		}
		return NodeFinder.perform(root, hoverRegion.getOffset(), hoverRegion.getLength());
	}

	private boolean isArrayTypeVariable(IJavaElement element) throws JavaModelException {
		String signature;
		if (element instanceof IField) {
			signature = ((IField) element).getTypeSignature();
		} else if (element instanceof ILocalVariable) {
			signature = ((ILocalVariable) element).getTypeSignature();
		} else {
			signature = ""; //$NON-NLS-1$
		}
		return signature.startsWith("["); //$NON-NLS-1$
	}

	private boolean isLocalOrMemberVariable(IJavaElement element) {
		return (element instanceof IField) || (element instanceof ILocalVariable);
	}

	private boolean isOverNameLength(IRegion hoverRegion, IDocument document) {
		try {
			return "length".equals(document.get(hoverRegion.getOffset(), hoverRegion.getLength())); //$NON-NLS-1$
		} catch (BadLocationException e) {
			return false;
		}
	}

	private IJavaElement[] resolveElement(int offset, ICodeAssist codeAssist) {
		IJavaElement[] resolve;
		try {
			resolve = codeAssist.codeSelect(offset, 0);
		} catch (JavaModelException e1) {
			resolve = new IJavaElement[0];
		}
		return resolve;
	}

	private IJavaVariable evaluateField(IJavaStackFrame frame, IField field) throws DebugException {
		IJavaObject ths = frame.getThis();
		if (ths != null) {
			String typeSignature = Signature.createTypeSignature(field.getDeclaringType().getFullyQualifiedName(), true);
			typeSignature = typeSignature.replace('.', '/');
			return ths.getField(field.getElementName(), typeSignature);
		}
		return null;
	}

	private IJavaVariable evaluateQualifiedNode(ASTNode node, IJavaStackFrame frame, IJavaProject project) {
		StringBuilder snippetBuilder = new StringBuilder();
		if (node instanceof QualifiedName) {
			snippetBuilder.append(((QualifiedName) node).getFullyQualifiedName());
		} else if (node instanceof FieldAccess) {
			StringJoiner segments = new StringJoiner("."); //$NON-NLS-1$
			node.accept(new ASTVisitor() {
				@Override
				public boolean visit(SimpleName node) {
					segments.add(node.getFullyQualifiedName());
					return true;
				}

				@Override
				public boolean visit(ThisExpression node) {
					segments.add("this"); //$NON-NLS-1$
					return true;
				}

			});
			snippetBuilder.append(segments.toString());
		} else {
			return null;
		}

		final String snippet = snippetBuilder.toString();
		class Evaluator implements IEvaluationListener {
			private CompletableFuture<IEvaluationResult> result = new CompletableFuture<>();

			@Override
			public void evaluationComplete(IEvaluationResult result) {
				this.result.complete(result);
			}

			public void run() throws DebugException {
				IAstEvaluationEngine engine = JDIDebugPlugin.getDefault().getEvaluationEngine(project, (IJavaDebugTarget) frame.getDebugTarget());
				engine.evaluate(snippet, frame, this, DebugEvent.EVALUATION_IMPLICIT, false);
			}

			public Optional<IEvaluationResult> getResult() {
				try {
					return Optional.ofNullable(result.get());
				} catch (InterruptedException e) {
					Thread.currentThread().interrupt();
				} catch (ExecutionException e) {
					JDIDebugUIPlugin.log(e);
				}
				return Optional.empty();
			}
		}
		Evaluator evaluator = new Evaluator();
		try {
			evaluator.run();
		} catch (DebugException e) {
			JDIDebugUIPlugin.log(e);
		}
		return evaluator.getResult().flatMap(r -> Optional.ofNullable(r.getValue()))
				.map(r -> new JDIPlaceholderVariable(snippet, r)).orElse(null);
	}

	public IInformationControlCreator getInformationPresenterControlCreator() {
		return new ExpressionInformationControlCreator();
	}
}
