/*=============================================================================#
 # Copyright (c) 2010, 2020 Stephan Wahlbrink and others.
 # 
 # This program and the accompanying materials are made available under the
 # terms of the Eclipse Public License 2.0 which is available at
 # https://www.eclipse.org/legal/epl-2.0, or the Apache License, Version 2.0
 # which is available at https://www.apache.org/licenses/LICENSE-2.0.
 # 
 # SPDX-License-Identifier: EPL-2.0 OR Apache-2.0
 # 
 # Contributors:
 #     Stephan Wahlbrink <sw@wahlbrink.eu> - initial API and implementation
 #=============================================================================*/

package org.eclipse.statet.internal.r.ui.rhelp;

import static org.eclipse.debug.ui.IDebugUIConstants.PREF_DETAIL_PANE_FONT;

import static org.eclipse.statet.ltk.ui.sourceediting.assist.InfoHover.MODE_FOCUS;
import static org.eclipse.statet.r.ui.rhelp.RHelpUI.RHELP_VIEW_IMAGE_ID;

import java.net.URI;
import java.net.URISyntaxException;

import org.eclipse.core.commands.ExecutionException;
import org.eclipse.core.commands.IHandler2;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Platform;
import org.eclipse.jface.action.Separator;
import org.eclipse.jface.action.ToolBarManager;
import org.eclipse.jface.internal.text.html.BrowserInformationControl;
import org.eclipse.jface.resource.JFaceResources;
import org.eclipse.jface.text.AbstractInformationControl;
import org.eclipse.jface.text.AbstractReusableInformationControlCreator;
import org.eclipse.jface.text.IInformationControl;
import org.eclipse.jface.text.IInformationControlCreator;
import org.eclipse.jface.text.IInformationControlExtension2;
import org.eclipse.jface.util.IPropertyChangeListener;
import org.eclipse.jface.util.PropertyChangeEvent;
import org.eclipse.jface.viewers.StyledString;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.browser.OpenWindowListener;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.browser.TitleEvent;
import org.eclipse.swt.browser.TitleListener;
import org.eclipse.swt.browser.WindowEvent;
import org.eclipse.swt.custom.StyledText;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontMetrics;
import org.eclipse.swt.graphics.GC;
import org.eclipse.swt.graphics.Image;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Menu;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.ui.IWorkbenchCommandConstants;
import org.eclipse.ui.IWorkbenchPage;
import org.eclipse.ui.PlatformUI;
import org.eclipse.ui.menus.CommandContributionItemParameter;
import org.eclipse.ui.services.IServiceLocator;

import org.eclipse.statet.ecommons.ui.SharedUIResources;
import org.eclipse.statet.ecommons.ui.actions.HandlerCollection;
import org.eclipse.statet.ecommons.ui.actions.HandlerContributionItem;
import org.eclipse.statet.ecommons.ui.actions.SimpleContributionItem;
import org.eclipse.statet.ecommons.ui.mpbv.BrowserHandler.IBrowserProvider;
import org.eclipse.statet.ecommons.ui.mpbv.BrowserHandler.NavigateBackHandler;
import org.eclipse.statet.ecommons.ui.mpbv.BrowserHandler.NavigateForwardHandler;
import org.eclipse.statet.ecommons.ui.util.InformationDispatchHandler;
import org.eclipse.statet.ecommons.ui.util.LayoutUtils;
import org.eclipse.statet.ecommons.ui.util.PixelConverter;
import org.eclipse.statet.ecommons.ui.util.UIAccess;

import org.eclipse.statet.r.core.RCore;
import org.eclipse.statet.r.ui.RUI;
import org.eclipse.statet.r.ui.rhelp.RHelpUI;
import org.eclipse.statet.rhelp.core.http.RHelpHttpService;


public class RHelpInfoHoverCreator extends AbstractReusableInformationControlCreator {
	
	
	public static final boolean isAvailable(final Composite parent) {
		return BrowserInformationControl.isAvailable(parent);
	}
	
	
	public static class Data {
		
		private final Control control;
		
		final Object helpObject;
		final URI httpUrl;
		
		public Data(final Control control, final Object helpObject, final URI httpUrl) {
			this.control= control;
			this.helpObject= helpObject;
			this.httpUrl= httpUrl;
		}
		
		
		public Control getControl() {
			return this.control;
		}
		
	}
	
	
	private final int mode;
	
	
	public RHelpInfoHoverCreator(final int mode) {
		this.mode= mode;
	}
	
	
	@Override
	protected IInformationControl doCreateInformationControl(final Shell parent) {
		return ((this.mode & MODE_FOCUS) != 0) ?
				new RHelpInfoControl(parent, this.mode, true) :
				new RHelpInfoControl(parent, this.mode);
	}
	
}

class RHelpInfoControl extends AbstractInformationControl implements IInformationControlExtension2,
		IPropertyChangeListener, OpenWindowListener, LocationListener, ProgressListener, TitleListener,
		IBrowserProvider {
	
	
	/** Action id (command) to navigate one page back. */
	protected static final String NAVIGATE_BACK_COMMAND_ID= IWorkbenchCommandConstants.NAVIGATE_BACK;
	/** Action id (command) to navigate one page forward. */
	protected static final String NAVIGATE_FORWARD_COMMAND_ID= IWorkbenchCommandConstants.NAVIGATE_FORWARD;
	
	
	/**
	 * Cached scroll bar width and height
	 */
	private static Point gScrollBarSize;
	
	
	private final int mode;
	
	private RHelpLabelProvider labelProvider;
	
	private Composite contentComposite;
	private Label titleImage;
	private StyledText titleText;
	private Browser infoBrowser;
	
	private final HandlerCollection handlerCollection= new HandlerCollection();
	
	private boolean layoutWorkaround;
	private boolean layoutHint;
	
	private RHelpInfoHoverCreator.Data input;
	private boolean inputChanged;
	
	private boolean loadingCompleted;
	private String browserTitle;
	
	private boolean hide;
	
	
	RHelpInfoControl(final Shell shell, final int mode) {
		super(shell, ""); //$NON-NLS-1$
		assert ((mode & MODE_FOCUS) == 0);
		this.mode= mode;
		
		JFaceResources.getFontRegistry().addListener(this);
		create();
	}
	
	RHelpInfoControl(final Shell shell, final int mode, final boolean dummy) {
		super(shell, new ToolBarManager(SWT.FLAT));
		assert ((mode & MODE_FOCUS) != 0);
		this.mode= mode;
		
		create();
	}
	
	
	@Override
	public void setInput(final Object input) {
		this.inputChanged= true;
		if (input instanceof RHelpInfoHoverCreator.Data) {
			this.input= (RHelpInfoHoverCreator.Data) input;
		}
		else {
			this.input= null;
		}
	}
	
	@Override
	public boolean hasContents() {
		return (this.input != null);
	}
	
	@Override
	protected void createContent(final Composite parent) {
		this.contentComposite= new Composite(parent, SWT.NONE) {
			@Override
			public Point computeSize(final int width, final int height, final boolean changed) {
				return super.computeSize(width, height, changed || width != getSize().x);
			}
		};
		this.contentComposite.setBackgroundMode(SWT.INHERIT_FORCE);
		
		final GridLayout gridLayout= LayoutUtils.newCompositeGrid(2);
		gridLayout.horizontalSpacing= (int) ((gridLayout.horizontalSpacing) / 1.5);
		this.contentComposite.setLayout(gridLayout);
		
		final int vIndent= Math.max(1, LayoutUtils.defaultVSpacing() / 4);
		final int hIndent= Math.max(3, LayoutUtils.defaultHSpacing() / 3);
		
		{	// Title image
			this.titleImage= new Label(this.contentComposite, SWT.NULL);
			final Image image= SharedUIResources.getImages().get(SharedUIResources.PLACEHOLDER_IMAGE_ID);
			this.titleImage.setImage(image);
			
			final GridData textGd= new GridData(SWT.FILL, SWT.TOP, false, false);
			this.titleText= new StyledText(this.contentComposite, SWT.MULTI | SWT.READ_ONLY | SWT.WRAP) {
				@Override
				public Point computeSize(int width, final int height, final boolean changed) {
					if (!RHelpInfoControl.this.layoutHint && width <= 0 && RHelpInfoControl.this.contentComposite.getSize().x > 0) {
						width= RHelpInfoControl.this.contentComposite.getSize().x -
								LayoutUtils.defaultHMargin() - RHelpInfoControl.this.titleImage.getSize().x - LayoutUtils.defaultHSpacing() - 10;
					}
					
					final Point size= super.computeSize(width, -1, true);
//					if (width >= 0) {
//						size.x= Math.min(size.x, width);
//					}
					return size;
				}
			};
			
			this.titleText.setFont(JFaceResources.getDialogFont());
			final GC gc= new GC(this.titleText);
			final FontMetrics fontMetrics= gc.getFontMetrics();
			final GridData imageGd= new GridData(SWT.FILL, SWT.TOP, false, false);
			imageGd.horizontalIndent= hIndent - 2;
			final int textHeight= fontMetrics.getAscent() + fontMetrics.getLeading();
			final int imageHeight= image.getBounds().height;
			final int shift= Math.max(3, (int) ((fontMetrics.getDescent()) / 1.5));
			if (textHeight+shift < imageHeight) {
				imageGd.verticalIndent= vIndent+shift;
				textGd.verticalIndent= vIndent+(imageHeight-textHeight);
			}
			else {
				imageGd.verticalIndent= vIndent+(textHeight-imageHeight)+shift;
				textGd.verticalIndent= vIndent;
			}
			this.titleImage.setLayoutData(imageGd);
			this.titleText.setLayoutData(textGd);
			this.layoutWorkaround= true;
			
			gc.dispose();
		}
		
		this.infoBrowser= new Browser(this.contentComposite, SWT.NONE);
		
		this.infoBrowser.addOpenWindowListener(this);
		this.infoBrowser.addLocationListener(this);
		this.infoBrowser.addProgressListener(this);
		this.infoBrowser.addTitleListener(this);
		
		this.infoBrowser.addOpenWindowListener(new OpenWindowListener() {
			@Override
			public void open(final WindowEvent event) {
				event.required= true;
			}
		});
		// Disable context menu
		this.infoBrowser.setMenu(new Menu(getShell(), SWT.NONE));
		
		final GridData gd= new GridData(SWT.FILL, SWT.FILL, true, true, 2, 1);
//		gd.widthHint= LayoutUtils.hintWidth(fInfoText, INFO_FONT, 50);
		this.infoBrowser.setLayoutData(gd);
		
		this.infoBrowser.addKeyListener(new KeyListener() {
			@Override
			public void keyPressed(final KeyEvent e)  {
				if (e.character == SWT.ESC) {
					dispose();
				}
			}
			@Override
			public void keyReleased(final KeyEvent e) {}
		});
		
		setBackgroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_BACKGROUND));
		setForegroundColor(getShell().getDisplay().getSystemColor(SWT.COLOR_INFO_FOREGROUND));
		
		if ((this.mode & MODE_FOCUS) != 0) {
			initActions(this.handlerCollection);
			final ToolBarManager toolBarManager= getToolBarManager();
			contributeToActionBars(PlatformUI.getWorkbench(), toolBarManager, this.handlerCollection);
			toolBarManager.update(true);
		}
		
		updateInput();
	}
	
	protected void initActions(final HandlerCollection handlers) {
		{	final IHandler2 handler= new NavigateBackHandler(this);
			handlers.add(NAVIGATE_BACK_COMMAND_ID, handler);
//			handlerService.activateHandler(NAVIGATE_BACK_COMMAND_ID, handler);
//			handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_BACKWARD_HISTORY, handler);
		}
		{	final IHandler2 handler= new NavigateForwardHandler(this);
			handlers.add(NAVIGATE_FORWARD_COMMAND_ID, handler);
//			handlerService.activateHandler(NAVIGATE_FORWARD_COMMAND_ID, handler);
//			handlerService.activateHandler(IWorkbenchCommandConstants.NAVIGATE_FORWARD_HISTORY, handler);
		}
	}
	
	protected void contributeToActionBars(final IServiceLocator serviceLocator,
			final ToolBarManager toolBarManager, final HandlerCollection handlers) {
		toolBarManager.add(
				new HandlerContributionItem(new CommandContributionItemParameter(
						serviceLocator, null, NAVIGATE_BACK_COMMAND_ID, HandlerContributionItem.STYLE_PUSH),
						handlers.get(NAVIGATE_BACK_COMMAND_ID) ));
		toolBarManager.add(
				new HandlerContributionItem(new CommandContributionItemParameter(
						serviceLocator, null, NAVIGATE_FORWARD_COMMAND_ID, HandlerContributionItem.STYLE_PUSH),
						handlers.get(NAVIGATE_FORWARD_COMMAND_ID) ));
		
		toolBarManager.add(new Separator());
		toolBarManager.add(new SimpleContributionItem(
				"Show in R Help View", "V",
				RHelpUI.getUIResources().getImageDescriptor(RHELP_VIEW_IMAGE_ID),
				null ) {
			@Override
			protected void execute() throws ExecutionException {
				if (UIAccess.isOkToUse(RHelpInfoControl.this.infoBrowser)) {
					try {
						final String urlString= RHelpInfoControl.this.infoBrowser.getUrl();
						final IWorkbenchPage page= UIAccess.getActiveWorkbenchPage(true);
						final RHelpView view= (RHelpView) page.showView(RUI.R_HELP_VIEW_ID);
						final URI browseUrl= RCore.getRHelpHttpService().toHttpUrl(urlString,
								null, RHelpHttpService.BROWSE_TARGET );
						if (browseUrl != null) {
							view.openUrl(browseUrl, null);
						}
						else {
							view.openUrl(urlString, null);
						}
					}
					catch (final Exception e) {}
				}
			}
		});
	}
	
	
	@Override
	public Browser getBrowser() {
		return this.infoBrowser;
	}
	
	@Override
	public void showMessage(final IStatus status) {
	}
	
	@Override
	public void changing(final LocationEvent event) {
		if (event.location.startsWith("http://")) { //$NON-NLS-1$
			try {
				if (RCore.getRHelpHttpService().isDynamicUrl(new URI(event.location))) {
					return;
				}
			}
			catch (final Exception e) {}
		}
		if (event.location.equals("about:blank")) { //$NON-NLS-1$
			return;
		}
		event.doit= false;
	}
	
	@Override
	public void changed(final LocationEvent event) {
		if (!event.top) {
			return;
		}
		final String url= this.infoBrowser.getUrl();
		final Object obj= RCore.getRHelpHttpService().getContentOfUrl(url);
		updateTitle(obj, this.browserTitle);
	}
	
	@Override
	public void changed(final ProgressEvent event) {
		this.handlerCollection.update(null);
	}
	
	@Override
	public void completed(final ProgressEvent event) {
		this.loadingCompleted= true;
		this.handlerCollection.update(null);
	}
	
	@Override
	public void changed(final TitleEvent event) {
		String title= event.title;
		if (title == null) {
			title= ""; //$NON-NLS-1$
		}
		else if (title.startsWith("http://")) { //$NON-NLS-1$
			final int idx= title.lastIndexOf('/');
			if (idx >= 0) {
				title= title.substring(idx+1);
			}
		}
		this.browserTitle= title;
	}
	
	@Override
	public void open(final WindowEvent event) {
		event.required= true;
	}
	
	
	@Override
	public void setBackgroundColor(final Color background) {
		super.setBackgroundColor(background);
		this.contentComposite.setBackground(background);
		this.infoBrowser.setBackground(background);
	}
	
	@Override
	public void setForegroundColor(final Color foreground) {
		super.setForegroundColor(foreground);
		this.contentComposite.setForeground(foreground);
		this.titleText.setForeground(foreground);
		this.infoBrowser.setForeground(foreground);
	}
	
	@Override
	public void setSize(final int width, final int height) {
		this.infoBrowser.setRedraw(false); // avoid flickering
		try {
			super.setSize(width, height);
		}
		finally {
			this.infoBrowser.setRedraw(true);
		}
	}
	
	
	@Override
	public Rectangle computeTrim() {
		final Rectangle trim= super.computeTrim();
		
		final Rectangle textTrim= this.infoBrowser.computeTrim(0, 0, 0, 0);
		if ((this.mode & MODE_FOCUS) != 0 && textTrim.width == 0) {
			if (gScrollBarSize == null) {
				final Text text= new Text(this.contentComposite, SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL | SWT.BORDER);
				gScrollBarSize= new Point(
						text.getVerticalBar().getSize().x,
						text.getHorizontalBar().getSize().y);
				text.dispose();
			}
			textTrim.x= 0;
			textTrim.y= 0;
			textTrim.width= gScrollBarSize.x;
			textTrim.height= gScrollBarSize.y;
		}
		trim.x+= textTrim.x;
		trim.y+= textTrim.y;
		trim.width+= textTrim.width;
		trim.height+= textTrim.height;
		
		return trim;
	}
	
	@Override
	public Point computeSizeHint() {
		updateInput();
		final Point sizeConstraints= getSizeConstraints();
		final Rectangle trim= computeTrim();
		
		this.titleText.setFont(JFaceResources.getDialogFont());
		final PixelConverter converter= new PixelConverter(this.titleText);
		int widthHint= converter.convertWidthInCharsToPixels(60);
		final GC gc= new GC(this.contentComposite);
		gc.setFont(JFaceResources.getTextFont());
		widthHint= Math.max(widthHint, (int)(gc.getFontMetrics().getAverageCharacterWidth() * 60 + 0x0.FFFFFp0));
		gc.dispose();
		
		final int heightHint= this.titleText.getLineHeight() * 12;
		
		final int widthMax= ((sizeConstraints != null && sizeConstraints.x != SWT.DEFAULT) ?
				sizeConstraints.x : widthHint+100) - trim.width;
		final int heightMax= ((sizeConstraints != null && sizeConstraints.y != SWT.DEFAULT) ?
				sizeConstraints.y : this.titleText.getLineHeight()*12) - trim.height;
		
		final Point size= new Point(widthHint, heightHint);
		size.y+= LayoutUtils.defaultVSpacing();
		size.x= Math.max(Math.min(size.x, widthMax), 200) + trim.width;
		size.y= Math.max(Math.min(size.y, heightMax), 100) + trim.height;
		return size;
	}
	
	@Override
	public Point computeSizeConstraints(final int widthInChars, final int heightInChars) {
		final int width= LayoutUtils.hintWidth(this.titleText, JFaceResources.DIALOG_FONT, widthInChars);
		final int lineHeight= this.titleText.getLineHeight();
		
		return new Point(width, lineHeight * heightInChars + LayoutUtils.defaultVSpacing());
	}
	
	@Override
	public void setVisible(final boolean visible) {
		if (visible) {
			this.hide= false;
			updateInput();
			waitCompleted();
			final Shell shell;
			if (this.hide || !UIAccess.isOkToUse(shell= getShell())) {
				return;
			}
			
			if (this.layoutWorkaround) {
				this.contentComposite.layout(true, true);
				this.layoutWorkaround= false;
			}
			
			if (Platform.WS_WIN32.equals(SWT.getPlatform())) {
				shell.moveAbove(null);
			}
		}
		else {
			this.hide= true;
		}
		super.setVisible(visible);
	}
	
	private void waitCompleted() {
		final Display display= Display.getCurrent();
		display.timerExec(200, new Runnable() {
			@Override
			public void run() {
				RHelpInfoControl.this.loadingCompleted= true;
			}
		});
		while (!this.loadingCompleted) {
			// Drive the event loop to process the events required to load the browser widget's contents:
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}
	
	@Override
	public void setFocus() {
		this.infoBrowser.setFocus();
	}
	
	private void updateInput() {
		if (this.infoBrowser == null || !this.inputChanged) {
			return;
		}
		if (this.labelProvider == null) {
			this.labelProvider= new RHelpLabelProvider(RHelpLabelProvider.WITH_TITLE | RHelpLabelProvider.WITH_QUALIFIER | RHelpLabelProvider.HEADER);
		}
		this.loadingCompleted= false;
		this.inputChanged= false;
		this.browserTitle= null;
		updateTitle(this.input.helpObject, null);
		if (this.input != null && this.input.httpUrl != null) {
			URI url= this.input.httpUrl;
			if ((this.mode & MODE_FOCUS) == 0) { // disable scrollbars
				try {
					url= new URI(url.toString() +
							'?' + RHelpUIServlet.STYLE_PARAM + '=' + RHelpUIServlet.HOVER_STYLE );
				}
				catch (final URISyntaxException e) {}
			}
			this.infoBrowser.setUrl(url.toString());
		}
		else {
			this.infoBrowser.setUrl("about:blank"); //$NON-NLS-1$
		}
		if ((this.mode & MODE_FOCUS) == 0) {
			setStatusText((this.input.getControl() != null
							&& this.input.getControl().isFocusControl() ) ?
					InformationDispatchHandler.getAffordanceString(this.mode) : "" ); //$NON-NLS-1$
		}
	}
	
	private void updateTitle(final Object helpObject, final String alt) {
		if (helpObject != null) {
			final Image image= this.labelProvider.getImage(helpObject);
			this.titleImage.setImage((image != null) ? image : SharedUIResources.getImages().get(SharedUIResources.PLACEHOLDER_IMAGE_ID));
			final StyledString styleString= this.labelProvider.getStyledText(helpObject);
			this.titleText.setText(styleString.getString());
			this.titleText.setStyleRanges(styleString.getStyleRanges());
		}
		else {
			this.titleImage.setImage(SharedUIResources.getImages().get(SharedUIResources.PLACEHOLDER_IMAGE_ID));
			this.titleText.setText((alt != null) ? alt : ""); //$NON-NLS-1$
		}
	}
	
	
	@Override
	public IInformationControlCreator getInformationPresenterControlCreator() {
		// enriched mode
		return new RHelpInfoHoverCreator(this.mode | MODE_FOCUS);
	}
	
	@Override
	public void propertyChange(final PropertyChangeEvent event) {
		final String property= event.getProperty();
		if (property.equals(PREF_DETAIL_PANE_FONT) || property.equals(JFaceResources.DEFAULT_FONT)) {
			dispose();
		}
	}
	
	@Override
	public void dispose() {
		JFaceResources.getFontRegistry().removeListener(this);
		this.handlerCollection.dispose();
		super.dispose();
	}
	
}
