/*******************************************************************************
 * Copyright (c) 2000, 2016 IBM Corporation and others.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.help.ui.internal.browser.embedded;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.Vector;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.core.runtime.IProduct;
import org.eclipse.core.runtime.Path;
import org.eclipse.core.runtime.Platform;
import org.eclipse.core.runtime.preferences.IEclipsePreferences;
import org.eclipse.core.runtime.preferences.InstanceScope;
import org.eclipse.help.internal.base.BaseHelpSystem;
import org.eclipse.help.internal.base.HelpApplication;
import org.eclipse.help.internal.util.ProductPreferences;
import org.eclipse.help.ui.internal.HelpUIPlugin;
import org.eclipse.help.ui.internal.Messages;
import org.eclipse.jface.resource.ImageDescriptor;
import org.eclipse.osgi.util.NLS;
import org.eclipse.swt.SWT;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.LocationAdapter;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.browser.VisibilityWindowListener;
import org.eclipse.swt.browser.WindowEvent;
import org.eclipse.swt.events.ControlEvent;
import org.eclipse.swt.events.ControlListener;
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.Label;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.osgi.framework.Bundle;
/**
 * Help browser employing SWT Browser widget
 */
public class EmbeddedBrowser {
	private static final String BROWSER_X = "browser.x"; //$NON-NLS-1$
	private static final String BROWSER_Y = "browser.y"; //$NON-NLS-1$
	private static final String BROWSER_WIDTH = "browser.w"; //$NON-NLS-1$
	private static final String BROWSER_HEIGTH = "browser.h"; //$NON-NLS-1$
	private static final String BROWSER_MAXIMIZED = "browser.maximized"; //$NON-NLS-1$
	private static String initialTitle = getWindowTitle();
	private Shell shell;
	private Browser browser;
	private Composite statusBar;
	private Label statusBarText;
	private Label statusBarSeparator;
	private ProgressBar statusBarProgress;
	private String statusText;
	private int x, y, w, h;
	private long modalRequestTime = 0;
	private Vector<IBrowserCloseListener> closeListeners = new Vector<>(1);
	/**
	 * Constructor for main help window instance
	 */
	public EmbeddedBrowser() {
		int style = SWT.SHELL_TRIM;
		if (ProductPreferences.isRTL())
			style |= SWT.RIGHT_TO_LEFT;
		else
			style |= SWT.LEFT_TO_RIGHT;
		shell = new Shell(style);
		initializeShell(shell);
		shell.addControlListener(new ControlListener() {

			@Override
			public void controlMoved(ControlEvent e) {
				if (!shell.getMaximized()) {
					Point location = shell.getLocation();
					x = location.x;
					y = location.y;
				}
			}

			@Override
			public void controlResized(ControlEvent e) {
				if (!shell.getMaximized()) {
					Point size = shell.getSize();
					w = size.x;
					h = size.y;
				}
			}
		});
		shell.addDisposeListener(e -> {
			// save position
			IEclipsePreferences prefs = InstanceScope.INSTANCE.getNode(HelpUIPlugin.PLUGIN_ID);
			prefs.putInt(BROWSER_X, x);
			prefs.putInt(BROWSER_Y, y);
			prefs.putInt(BROWSER_WIDTH, w);
			prefs.putInt(BROWSER_HEIGTH, h);
			prefs.putBoolean(BROWSER_MAXIMIZED, (shell.getMaximized()));
			notifyCloseListners();
			if (HelpApplication.isShutdownOnClose()) {
				HelpApplication.stopHelp();
			}
		});

		browser = new Browser(shell, SWT.NONE);
		browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));
		initialize(browser);

		createStatusBar(shell);
		initializeStatusBar(browser);

		// use saved location and size
		x = Platform.getPreferencesService().getInt(HelpUIPlugin.PLUGIN_ID, BROWSER_X, 0, null);
		y = Platform.getPreferencesService().getInt(HelpUIPlugin.PLUGIN_ID, BROWSER_Y, 0, null);
		w = Platform.getPreferencesService().getInt(HelpUIPlugin.PLUGIN_ID, BROWSER_WIDTH, 0, null);
		h = Platform.getPreferencesService().getInt(HelpUIPlugin.PLUGIN_ID, BROWSER_HEIGTH, 0, null);
		if (w == 0 || h == 0) {
			// first launch, use default size
			w = 1024;
			h = 768;
			x = shell.getLocation().x;
			y = shell.getLocation().y;
		}
		setSafeBounds(shell, x, y, w, h);
		if (Platform.getPreferencesService().getBoolean(HelpUIPlugin.PLUGIN_ID, BROWSER_MAXIMIZED, false, null))
			shell.setMaximized(true);
		shell.addControlListener(new ControlListener() {

			@Override
			public void controlMoved(ControlEvent e) {
				if (!shell.getMaximized()) {
					Point location = shell.getLocation();
					x = location.x;
					y = location.y;
				}
			}

			@Override
			public void controlResized(ControlEvent e) {
				if (!shell.getMaximized()) {
					Point size = shell.getSize();
					w = size.x;
					h = size.y;
				}
			}
		});

		//
		shell.open();
		//browser.setUrl("about:blank");

		browser.addLocationListener(new LocationAdapter() {

			@Override
			public void changing(LocationEvent e) {
				// hack to know when help webapp needs modal window
				modalRequestTime = 0;
				if (e.location != null
						&& e.location.startsWith("javascript://needModal")) { //$NON-NLS-1$
					modalRequestTime = System.currentTimeMillis();
				}
				if (!e.doit && e.location != null
						&& e.location.startsWith("https://")) { //$NON-NLS-1$
					try {
						BaseHelpSystem.getHelpBrowser(true).displayURL(
								e.location);
					} catch (Exception exc) {
					}
				}
			}
		});
	}
	/**
	 * Constructor for derived help window It is either secondary browser or a
	 * help dialog
	 *
	 * @param event
	 * @param parent
	 *            Shell or null
	 */
	public EmbeddedBrowser(WindowEvent event, Shell parent) {
		if (parent == null){
			int style = SWT.SHELL_TRIM;
			if (ProductPreferences.isRTL())
				style |= SWT.RIGHT_TO_LEFT;
			else
				style |= SWT.LEFT_TO_RIGHT;
			shell = new Shell(style);
		} else
			shell = new Shell(parent, SWT.PRIMARY_MODAL | SWT.DIALOG_TRIM | SWT.RESIZE);
		initializeShell(shell);
		Browser browser = new Browser(shell, SWT.NONE);
		browser.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, true));

		initialize(browser);
		event.browser = browser;

		browser.addLocationListener(new LocationAdapter() {

			@Override
			public void changing(LocationEvent e) {
				// hack to know when help webapp needs modal window
				modalRequestTime = 0;
				if (e.location != null
						&& e.location.startsWith("javascript://needModal")) { //$NON-NLS-1$
					modalRequestTime = System.currentTimeMillis();
				}
			}
		});
	}
	private static void initializeShell(Shell s) {
		s.setText(initialTitle);
		final Image[] shellImages = createImages();
		if (shellImages != null)
			s.setImages(shellImages);
		GridLayout layout = new GridLayout();
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		layout.verticalSpacing = 0;
		layout.horizontalSpacing = 0;
		s.setLayout(layout);
		s.addDisposeListener(e -> {
			if (shellImages != null) {
				for (int i = 0; i < shellImages.length; i++) {
					shellImages[i].dispose();
				}
			}
		});

	}
	private void initialize(Browser browser) {
		browser.addOpenWindowListener(event -> {
			if (System.currentTimeMillis() - modalRequestTime <= 1000) {
				new EmbeddedBrowser(event, shell);
			} else if (event.required) {
				new EmbeddedBrowser(event, null);
			} else {
				displayURLExternal(event);
			}
		});
		browser.addVisibilityWindowListener(new VisibilityWindowListener() {

			@Override
			public void hide(WindowEvent event) {
				Browser browser = (Browser) event.widget;
				Shell shell = browser.getShell();
				shell.setVisible(false);
			}

			@Override
			public void show(WindowEvent event) {
				Browser browser = (Browser) event.widget;
				Shell shell = browser.getShell();
				if (event.location != null)
					shell.setLocation(event.location);
				if (event.size != null) {
					Point size = event.size;
					shell.setSize(shell.computeSize(size.x, size.y));
				}
				shell.open();
			}
		});
		browser.addCloseWindowListener(event -> {
			Browser browser1 = (Browser) event.widget;
			Shell shell = browser1.getShell();
			shell.close();
		});
		browser.addTitleListener(event -> {
			if (event.title != null && event.title.length() > 0) {
				Browser browser1 = (Browser) event.widget;
				Shell shell = browser1.getShell();
				shell.setText(event.title);
			}
		});
		browser.addLocationListener(new LocationAdapter() {

			@Override
			public void changing(LocationEvent e) {
				if (!e.doit && e.location != null
						&& e.location.startsWith("https://")) { //$NON-NLS-1$
					try {
						BaseHelpSystem.getHelpBrowser(true).displayURL(
								e.location);
					} catch (Exception exc) {
					}
				}
			}
		});
	}

	private void initializeStatusBar(Browser browser) {
		browser.addStatusTextListener(event -> {
			event.text = event.text.replaceAll("&", "&&"); //$NON-NLS-1$ //$NON-NLS-2$
			if (!event.text.equals(statusText)) {
				statusText = event.text;
				statusBarText.setText(statusText);
			}
		});
		browser.addProgressListener(new ProgressListener() {

			@Override
			public void changed(ProgressEvent event) {
				if (event.total > 0) {
					statusBarProgress.setMaximum(event.total);
					statusBarProgress.setSelection(Math.min(event.current, event.total));
					statusBarSeparator.setVisible(true);
					statusBarProgress.setVisible(true);
				}
			}

			@Override
			public void completed(ProgressEvent event) {
				statusBarSeparator.setVisible(false);
				statusBarProgress.setVisible(false);
			}
		});
	}

	private void createStatusBar(Composite parent) {
		statusBar = new Composite(parent, SWT.NONE);
		statusBar.setLayoutData(new GridData(SWT.FILL, SWT.FILL, true, false));
		GridLayout layout =  new GridLayout(3, false);
		layout.marginWidth = 0;
		layout.marginHeight = 0;
		layout.marginTop = 0;
		layout.marginLeft = 5;
		layout.marginRight = 5;
		layout.marginBottom = 5;
		statusBar.setLayout(layout);
		statusBarText = new Label(statusBar, SWT.NONE);
		statusBarText.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, true, false));
		statusBarSeparator = new Label(statusBar, SWT.SEPARATOR | SWT.VERTICAL);
		statusBarSeparator.setVisible(false);
		statusBarProgress = new ProgressBar(statusBar, SWT.HORIZONTAL);
		GridData data = new GridData(SWT.FILL, SWT.CENTER, false, false);
		data.widthHint = 100;
		statusBarProgress.setLayoutData(data);
		statusBarProgress.setVisible(false);
		statusBarProgress.setMinimum(0);

		/*
		 * Vertical separator labels are naturally too tall for the status bar.
		 * Size it to match the tallest of the text and progress bar.
		 */
		data = new GridData(SWT.FILL, SWT.CENTER, false, false);
		data.heightHint = Math.max(statusBarText.computeSize(SWT.DEFAULT, SWT.DEFAULT).y, statusBarProgress.computeSize(SWT.DEFAULT, SWT.DEFAULT).y);
		statusBarSeparator.setLayoutData(data);
	}

	public void displayUrl(String url) {
		browser.setUrl(url);
		shell.setMinimized(false);
		shell.forceActive();
	}
	private void displayURLExternal(WindowEvent e) {
		final Shell externalShell = new Shell(shell, SWT.NONE);
		Browser externalBrowser = new Browser(externalShell, SWT.NONE);
		externalBrowser.addLocationListener(new LocationAdapter() {

			@Override
			public void changing(final LocationEvent e) {
				e.doit = false;
				try {
					BaseHelpSystem.getHelpBrowser(true).displayURL(e.location);
				}
				catch (Throwable t) {
					String msg = "Error opening external Web browser"; //$NON-NLS-1$
					HelpUIPlugin.logError(msg, t);
				}
				externalShell.getDisplay().asyncExec(() -> externalShell.dispose());
			}
		});
		e.browser = externalBrowser;
	}
	public boolean isDisposed() {
		return shell.isDisposed();
	}
	private static String getWindowTitle() {
		if (Platform.getPreferencesService().getBoolean(HelpUIPlugin.PLUGIN_ID, "windowTitlePrefix", false, null)) { //$NON-NLS-1$
			return NLS.bind(Messages.browserTitle, BaseHelpSystem
            .getProductName());
		}
		return BaseHelpSystem.getProductName();
	}
	/**
	 * Create shell images
	 */
	private static Image[] createImages() {
		String[] productImageURLs = getProductImageURLs();
		if (productImageURLs != null) {
			ArrayList<Image> shellImgs = new ArrayList<>();
			for (int i = 0; i < productImageURLs.length; i++) {
				if ("".equals(productImageURLs[i])) { //$NON-NLS-1$
					continue;
				}
				URL imageURL = null;
				try {
					imageURL = new URL(productImageURLs[i]);
				} catch (MalformedURLException mue) {
					// must be a path relative to the product bundle
					IProduct product = Platform.getProduct();
					if (product != null) {
						Bundle productBundle = product.getDefiningBundle();
						if (productBundle != null) {
							imageURL = FileLocator.find(productBundle, new Path(
									productImageURLs[i]), null);
						}
					}
				}
				Image image = null;
				if (imageURL != null) {
					image = ImageDescriptor.createFromURL(imageURL)
							.createImage();
				}
				if (image != null) {
					shellImgs.add(image);
				}
			}
			return shellImgs.toArray(new Image[shellImgs.size()]);
		}
		return new Image[0];
	}
	/**
	 * Obtains URLs to product image
	 *
	 * @return String[] with URLs as Strings or null
	 */
	private static String[] getProductImageURLs() {
		IProduct product = Platform.getProduct();
		if (product != null) {
			String url = product.getProperty("windowImages"); //$NON-NLS-1$
			if (url != null && url.length() > 0) {
				return url.split(",\\s*"); //$NON-NLS-1$
			}
			url = product.getProperty("windowImage"); //$NON-NLS-1$
			if (url != null && url.length() > 0) {
				return new String[]{url};
			}
		}
		return null;
	}
	/**
	 * Closes the browser.
	 */
	public void close() {
		if (!shell.isDisposed())
			shell.dispose();
	}
	private static void setSafeBounds(Shell s, int x, int y, int width,
			int height) {
		Rectangle clientArea = s.getDisplay().getClientArea();
		width = Math.min(clientArea.width, width);
		height = Math.min(clientArea.height, height);
		x = Math.min(x + width, clientArea.x + clientArea.width) - width;
		y = Math.min(y + height, clientArea.y + clientArea.height) - height;
		x = Math.max(x, clientArea.x);
		y = Math.max(y, clientArea.y);
		s.setBounds(x, y, width, height);
	}
	public void setLocation(int x, int y) {
		shell.setLocation(x, y);
	}
	public void setSize(int width, int height) {
		shell.setSize(w, h);
	}
	private void notifyCloseListners() {
		for (Iterator<IBrowserCloseListener> it = closeListeners.iterator(); it.hasNext();) {
			IBrowserCloseListener listener = it.next();
			listener.browserClosed();
		}
	}

	public void addCloseListener(IBrowserCloseListener listener) {
		if (!closeListeners.contains(listener)) {
			closeListeners.add(listener);
		}
	}

	public void removeCloseListener(IBrowserCloseListener listener) {
		closeListeners.remove(listener);
	}
}
