package snippet;

import java.util.concurrent.Semaphore;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTError;
import org.eclipse.swt.browser.CloseWindowListener;
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.StatusTextListener;
import org.eclipse.swt.browser.TitleListener;
import org.eclipse.swt.browser.VisibilityWindowAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.GridData;
import org.eclipse.swt.layout.GridLayout;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Label;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ProgressBar;
import org.eclipse.swt.widgets.Shell;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.ToolBar;
import org.eclipse.swt.widgets.ToolItem;

import javafx.application.Platform;
import javafx.embed.swt.FXCanvas;
import javafx.scene.Group;
import javafx.scene.Scene;
import javafx.scene.paint.Color;
import javafx.scene.web.WebView;

/**
 * WebView (webkit) wrapper.
 * not finished, see work to be done in org.eclipse.swt.browser.Webkit.class to make this class fully operational
 * 
 * @author mdecorde
 *
 */
public class JFXBrowser extends FXCanvas {
	
	protected static final String NOMEDIA = ""; //$NON-NLS-1$
	
	private WebView jfxBrowser;
	
	// private GLComposite videoComposite;
	
	public WebView getEmbeddedMediaPlayer() {
		return jfxBrowser;
	}
	
	Semaphore s = new Semaphore(1);
	
	// private FXCanvas fxCanvas;
	
	Point previousP;
	
	public JFXBrowser(Composite parent, int style) {
		super(parent, style);
		GridLayout gl = new GridLayout(1, true);
		gl.horizontalSpacing = 0;
		this.setLayout(gl);
		
		// THE PLAYER
		// if (RuntimeUtil.isMac()) {
		// try {
		// LibC.INSTANCE.setenv("VLC_PLUGIN_PATH", "/Applications/VLC.app/Contents/MacOS/plugins", 1);
		// }
		// catch (Exception ex) {
		// ex.printStackTrace();
		// }
		// }
		// videoComposite = new GLComposite(this, SWT.NONE, "Video");
		GridData gdata = new GridData(SWT.FILL, SWT.FILL, true, true);
		this.setLayoutData(gdata);
		jfxBrowser = null;
		
		this.addListener(SWT.Resize, new Listener() {
			
			@Override
			public void handleEvent(Event e) {
				resizeView();
			}
		});
		
		// fxCanvas = new FXCanvas(videoComposite, SWT.BORDER);
		// GridData gdata2 = new GridData(SWT.FILL, SWT.FILL, true, true);
		// fxCanvas.setLayoutData(gdata2);
		
		initializeBrowser();
	}
	
	// @Override
	// public void addMouseListener(MouseListener listener) {
	// // jfxBrowser.setOnMousePressed(new EventHandler<MouseEvent>() {
	// //
	// // @Override
	// // public void handle(MouseEvent event) {
	// // // TODO Auto-generated method stub
	// //
	// // }
	// // });
	// fxCanvas.addMouseListener(listener);
	// }
	
	protected void resizeView() {
		if (jfxBrowser != null) {
			Point p = this.getSize();
			// if (previousP == null || (p.x != previousP.x && p.y != previousP.y)) { // ensure size changed
			jfxBrowser.setPrefHeight(p.y);
			// jfxBrowser.setMaxWidth(p.x);
			jfxBrowser.setPrefWidth(p.x);
			previousP = p;
			// }
		}
	}
	
	private Group group;
	
	private Scene scene;
	
	protected boolean initializeBrowser() {
		
		Platform.setImplicitExit(false);
		jfxBrowser = new WebView();
		
		group = new Group(jfxBrowser);
		
		// scene = new Scene(group, Color.rgb(fxCanvas.getBackground().getRed(), fxCanvas.getBackground().getGreen(), fxCanvas.getBackground().getBlue()));
		scene = new Scene(group, Color.rgb(0, 0, 0));
		
		this.setScene(jfxBrowser.getScene());
		
		return true;
	}
	
	public boolean back() {
		try {
			jfxBrowser.getEngine().getHistory().go(-1);
			return true;
		}
		catch (Exception e) {
			return false;
		}
	}
	
	public boolean forward() {
		try {
			jfxBrowser.getEngine().getHistory().go(1);
			return true;
		}
		catch (Exception e) {
			return false;
		}
	}
	
	public void stop() {
		// jfxBrowser.getEngine().canc();
		System.out.println("TODO JFXBrowser.stop...");
	}
	
	public void refresh() {
		jfxBrowser.getEngine().reload();
	}
	
	public void setUrl(String url) {
		jfxBrowser.getEngine().load(url);
	}
	
	public void addProgressListener(ProgressListener progressListener) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.addProgressListener(" + progressListener + ")");
	}
	
	public void addStatusTextListener(StatusTextListener listener) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.addStatusTextListener(" + listener + ")");
	}
	
	public void addLocationListener(LocationListener locationListener) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.addLocationListener(" + locationListener + ")");
	}
	
	public void addOpenWindowListener(OpenWindowListener listener) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.addOpenWindowListener(" + listener + ")");
	}
	
	public void addVisibilityWindowListener(VisibilityWindowAdapter visibilityWindowAdapter) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.addVisibilityWindowListener(" + visibilityWindowAdapter + ")");
	}
	
	public void addCloseWindowListener(CloseWindowListener listener) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.addCloseWindowListener(" + listener + ")");
	}
	
	public void addTitleListener(TitleListener listener) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.addTitleListener(" + listener + ")");
	}
	
	public void removeLocationListener(LocationListener locationListener) {
		// TODO Auto-generated method stub
		System.out.println("TODO JFXBrowser.removeLocationListener(" + locationListener + ")");
	}
	
	public static void main(String[] args) {
		Display display = new Display();
		final Shell shell = new Shell(display);
		shell.setText("Snippet 128");
		GridLayout gridLayout = new GridLayout();
		gridLayout.numColumns = 3;
		shell.setLayout(gridLayout);
		ToolBar toolbar = new ToolBar(shell, SWT.NONE);
		ToolItem itemBack = new ToolItem(toolbar, SWT.PUSH);
		itemBack.setText("Back");
		ToolItem itemForward = new ToolItem(toolbar, SWT.PUSH);
		itemForward.setText("Forward");
		ToolItem itemStop = new ToolItem(toolbar, SWT.PUSH);
		itemStop.setText("Stop");
		ToolItem itemRefresh = new ToolItem(toolbar, SWT.PUSH);
		itemRefresh.setText("Refresh");
		ToolItem itemGo = new ToolItem(toolbar, SWT.PUSH);
		itemGo.setText("Go");
		
		GridData data = new GridData();
		data.horizontalSpan = 3;
		toolbar.setLayoutData(data);
		
		Label labelAddress = new Label(shell, SWT.NONE);
		labelAddress.setText("Address");
		
		final Text location = new Text(shell, SWT.BORDER);
		data = new GridData();
		data.horizontalAlignment = GridData.FILL;
		data.horizontalSpan = 2;
		data.grabExcessHorizontalSpace = true;
		location.setLayoutData(data);
		
		final JFXBrowser browser;
		try {
			browser = new JFXBrowser(shell, SWT.NONE);
		}
		catch (SWTError e) {
			System.out.println("Could not instantiate Browser: " + e.getMessage());
			display.dispose();
			return;
		}
		data = new GridData();
		data.horizontalAlignment = GridData.FILL;
		data.verticalAlignment = GridData.FILL;
		data.horizontalSpan = 3;
		data.grabExcessHorizontalSpace = true;
		data.grabExcessVerticalSpace = true;
		browser.setLayoutData(data);
		
		final Label status = new Label(shell, SWT.NONE);
		data = new GridData(GridData.FILL_HORIZONTAL);
		data.horizontalSpan = 2;
		status.setLayoutData(data);
		
		final ProgressBar progressBar = new ProgressBar(shell, SWT.NONE);
		data = new GridData();
		data.horizontalAlignment = GridData.END;
		progressBar.setLayoutData(data);
		
		/* event handling */
		Listener listener = event -> {
			ToolItem item = (ToolItem) event.widget;
			String string = item.getText();
			if (string.equals("Back"))
				browser.back();
			else if (string.equals("Forward"))
				browser.forward();
			else if (string.equals("Stop"))
				browser.stop();
			else if (string.equals("Refresh"))
				browser.refresh();
			else if (string.equals("Go"))
				browser.setUrl(location.getText());
		};
		browser.addProgressListener(new ProgressListener() {
			
			@Override
			public void changed(ProgressEvent event) {
				if (event.total == 0) return;
				int ratio = event.current * 100 / event.total;
				progressBar.setSelection(ratio);
			}
			
			@Override
			public void completed(ProgressEvent event) {
				progressBar.setSelection(0);
			}
		});
		
		browser.addLocationListener(new LocationListener() {
			
			@Override
			public void changing(LocationEvent event) {}
			
			@Override
			public void changed(LocationEvent event) {
				if (event.top) location.setText(event.location);
			}
		});
		// browser.addLocationListener(LocationListener.changed(event -> {
		// if (event.top) location.setText(event.location);
		// }));
		itemBack.addListener(SWT.Selection, listener);
		itemForward.addListener(SWT.Selection, listener);
		itemStop.addListener(SWT.Selection, listener);
		itemRefresh.addListener(SWT.Selection, listener);
		itemGo.addListener(SWT.Selection, listener);
		location.addListener(SWT.DefaultSelection, e -> browser.setUrl(location.getText()));
		
		browser.addMouseListener(new MouseListener() {
			
			@Override
			public void mouseUp(MouseEvent e) {
				System.out.println("M UP");
			}
			
			@Override
			public void mouseDown(MouseEvent e) {
				System.out.println("M DOWN");
			}
			
			@Override
			public void mouseDoubleClick(MouseEvent e) {
				System.out.println("M DCLICK");
			}
		});
		
		browser.addKeyListener(new KeyListener() {
			
			@Override
			public void keyReleased(KeyEvent e) {}
			
			@Override
			public void keyPressed(KeyEvent e) {
				System.out.println("K " + e);
			}
		});
		
		shell.open();
		// browser.setUrl("http://eclipse.org");
		
		while (!shell.isDisposed()) {
			if (!display.readAndDispatch())
				display.sleep();
		}
		display.dispose();
	}
	
	public WebView getWebView() {
		return this.jfxBrowser;
	}
	
	public String getUrl() {
		return jfxBrowser.getEngine().getLocation();
	}
	
	public boolean isBackEnabled() {
		return jfxBrowser.getEngine().getHistory().getCurrentIndex() > 0;
	}
	
	public boolean isForwardEnabled() {
		return jfxBrowser.getEngine().getHistory().getCurrentIndex() < jfxBrowser.getEngine().getHistory().getEntries().size();
	}
	
	public boolean setUrl(String url, String postData, String[] headers) {
		// TODO Auto-generated method stub
		jfxBrowser.getEngine().load(url);
		return true;
	}
}
