/*=============================================================================#
 # Copyright (c) 2009, 2018 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.rj.eclient.graphics;

import java.util.List;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.graphics.Rectangle;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Control;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Layout;
import org.eclipse.swt.widgets.Listener;
import org.eclipse.swt.widgets.ScrollBar;


/**
 * Composite to display an R graphic.
 */
public class RGraphicComposite extends Composite
		implements ERGraphic.ListenerInstructionsExtension, ERGraphic.ListenerLocatorExtension {
	
	
	/**
	 * This class provides the layout for RGraphicComposite
	 */
	private static class ScrolledCompositeLayout extends Layout {
		
		static final int DEFAULT_WIDTH	= 64;
		static final int DEFAULT_HEIGHT	= 64;
		
		
		private boolean inLayout= false;
		
		
		public ScrolledCompositeLayout() {
		}
		
		
		@Override
		protected boolean flushCache(final Control control) {
			return true;
		}
		
		@Override
		protected Point computeSize(final Composite composite, final int wHint, final int hHint, final boolean flushCache) {
			final RGraphicComposite sc= (RGraphicComposite) composite;
			final Point size= new Point(wHint, hHint);
			if (wHint == SWT.DEFAULT) {
				size.x= Math.max(DEFAULT_WIDTH, sc.width);
			}
			if (hHint == SWT.DEFAULT) {
				size.y= Math.max(DEFAULT_HEIGHT, sc.height);
			}
			return size;
		}
		
		@Override
		protected void layout(final Composite composite, final boolean flushCache) {
			if (this.inLayout || composite == null) {
				return;
			}
			final RGraphicComposite sc= (RGraphicComposite) composite;
			final ScrollBar hBar= sc.getHorizontalBar();
			final ScrollBar vBar= sc.getVerticalBar();
			
			if (hBar.getSize().y >= sc.getSize().y) {
				return;
			}
			if (vBar.getSize().x >= sc.getSize().x) {
				return;
			}
			
			this.inLayout= true;
			
			final Rectangle previousBounds= sc.canvas.getBounds();
			boolean hVisible= sc.needHBar(previousBounds, false);
			final boolean vVisible= sc.needVBar(previousBounds, hVisible);
			if (!hVisible && vVisible) {
				hVisible= sc.needHBar(previousBounds, vVisible);
			}
			hBar.setVisible(hVisible);
			vBar.setVisible(vVisible);
			
			final Rectangle clientArea= sc.getClientArea();
			final int x;
			final int y;
			final int width= sc.width;
			final int height= sc.height;
			hBar.setThumb(clientArea.width);
			hBar.setPageIncrement(clientArea.width);
			if (hVisible) {
				x= (sc.changedLayout || previousBounds.x >= 0) ? 0 :
						Math.max(previousBounds.x, clientArea.width - width);
				hBar.setSelection(-x);
			}
			else {
				x= (clientArea.width - width) / 2;
				hBar.setSelection(0);
			}
			vBar.setThumb(clientArea.height);
			vBar.setPageIncrement(clientArea.height);
			if (vVisible) {
				y= (sc.changedLayout || previousBounds.y >= 0) ? 0 :
						Math.max(previousBounds.y, clientArea.height - height);
				vBar.setSelection(-y);
			}
			else {
				y= (clientArea.height - height) / 2;
				vBar.setSelection(0);
			}
			
			sc.changedLayout= false;
			sc.canvas.setBounds(x, y, width, height);
			this.inLayout= false;
		}
		
	}
	
	private class PanListener implements Listener {
		
		private boolean started;
		private Point startMouse;
		
		@Override
		public void handleEvent(final Event event) {
			switch (event.type) {
			case SWT.MouseDown:
				if (event.button == 2) {
					this.started= true;
					updateCursor();
					
					this.startMouse= checkedPoint(event);
					return;
				}
				else {
					this.started= false;
					return;
				}
			case SWT.MouseExit:
			case SWT.MouseMove:
				if (this.started) {
					pan(checkedPoint(event));
					return;
				}
				else {
					return;
				}
			case SWT.MouseUp:
				if (this.started && event.button == 2) {
					this.started= false;
					updateCursor();
					return;
				}
				else {
					return;
				}
			case SWT.KeyDown:
				switch (event.keyCode) {
				case SWT.ARROW_DOWN:
					if (update(getVerticalBar(), RGraphicComposite.this.panIncrement)) {
						scrollV();
					}
					return;
				case SWT.ARROW_UP:
					if (update(getVerticalBar(), -RGraphicComposite.this.panIncrement)) {
						scrollV();
					}
					return;
				case SWT.ARROW_RIGHT:
					if (update(getHorizontalBar(), RGraphicComposite.this.panIncrement)) {
						scrollH();
					}
					return;
				case SWT.ARROW_LEFT:
					if (update(getHorizontalBar(), -RGraphicComposite.this.panIncrement)) {
						scrollH();
					}
					return;
				default:
					return;
				}
			}
		}
		
		private Point checkedPoint(final Event event) {
			if (event.item == RGraphicComposite.this) {
				return new Point(event.x, event.y);
			}
			else {
				final Point point= ((Control) event.widget).toDisplay(event.x, event.y);
				return RGraphicComposite.this.toControl(point);
			}
		}
		
		private void pan(final Point point) {
			if (update(getHorizontalBar(), this.startMouse.x - point.x)) {
				scrollH();
			}
			if (update(getVerticalBar(), this.startMouse.y - point.y)) {
				scrollV();
			}
			this.startMouse= point;
		}
		
		private boolean update(final ScrollBar bar, final int step) {
			if (bar != null && bar.isVisible()) {
				int selection= bar.getSelection() + step;
				if (selection < 0) {
					selection= 0;
				}
				else if (selection > bar.getMaximum()) {
					selection= bar.getMaximum() - bar.getThumb();
				}
				bar.setSelection(selection);
				return true;
			}
			return false;
		}
		
	}
	
	
	private static int checkStyle (final int style) {
		final int mask= SWT.H_SCROLL | SWT.V_SCROLL | SWT.BORDER | SWT.LEFT_TO_RIGHT | SWT.RIGHT_TO_LEFT;
		return style & mask;
	}
	
	
	private ERGraphic graphic;
	
	private RGraphicCanvas canvas;
	
	private int width= 0;
	private int height= 0;
	
	private boolean changedLayout;
	private boolean changedContent;
	
	private int panIncrement;
	private final PanListener panListener;
	
	private MouseListener locatorListener;
	
	
	public RGraphicComposite(final Composite parent, final ERGraphic graphic) {
		super(parent, checkStyle(SWT.H_SCROLL | SWT.V_SCROLL));
		super.setLayout(new ScrolledCompositeLayout());
		
		this.panIncrement= 10;
		
		final ScrollBar hBar= getHorizontalBar();
		hBar.setVisible(false);
		hBar.addListener(SWT.Selection, new Listener() {
			@Override
			public void handleEvent(final Event event) {
				scrollH();
			}
		});
		hBar.setIncrement(this.panIncrement);
		final ScrollBar vBar= getVerticalBar();
		vBar.setVisible(false);
		vBar.addListener(SWT.Selection, new Listener() {
			@Override
			public void handleEvent(final Event event) {
				scrollV();
			}
		});
		vBar.setIncrement(this.panIncrement);
		addListener(SWT.Resize, new Listener() {
			@Override
			public void handleEvent(final Event event) {
//				checkContentSize();
			}
		});
		createCanvas();
		final Listener updateListener= new Listener() {
			@Override
			public void handleEvent(final Event event) {
				if (RGraphicComposite.this.changedContent) {
					updateGraphic();
				}
			}
		};
		addListener(SWT.Show, updateListener);
		addListener(SWT.Activate, updateListener);
		
		this.panListener= new PanListener();
		addListener(SWT.MouseDown, this.panListener);
		addListener(SWT.MouseMove, this.panListener);
		addListener(SWT.MouseExit, this.panListener);
		addListener(SWT.MouseUp, this.panListener);
		addListener(SWT.KeyDown, this.panListener);
		this.canvas.addListener(SWT.MouseDown, this.panListener);
		this.canvas.addListener(SWT.MouseMove, this.panListener);
		this.canvas.addListener(SWT.MouseExit, this.panListener);
		this.canvas.addListener(SWT.MouseUp, this.panListener);
		this.canvas.addListener(SWT.KeyDown, this.panListener);
		
		setGraphic(graphic);
		
		addDisposeListener(new DisposeListener() {
			@Override
			public void widgetDisposed(final DisposeEvent e) {
				disconnect();
			}
		});
	}
	
	private void createCanvas() {
		this.canvas= new RGraphicCanvas(this);
	}
	
	boolean needHBar(final Rectangle contentRect, final boolean vVisible) {
		final Rectangle hostRect= getBounds();
		hostRect.width-= 2 * getBorderWidth();
		if (vVisible) {
			hostRect.width-= getVerticalBar().getSize().x;
		}
		return (this.width > hostRect.width);
	}
	
	boolean needVBar(final Rectangle contentRect, final boolean hVisible) {
		final Rectangle hostRect= getBounds();
		hostRect.height-= 2 * getBorderWidth();
		if (hVisible) {
			hostRect.height-= getHorizontalBar().getSize().y;
		}
		return (this.height > hostRect.height);
	}
	
	private void scrollH() {
		final Point location= this.canvas.getLocation();
		final ScrollBar hBar= getHorizontalBar();
		if (hBar != null && hBar.isVisible()) {
			final int hSelection= hBar.getSelection();
			this.canvas.setLocation(-hSelection, location.y);
		}
	}
	
	private void scrollV() {
		final Point location= this.canvas.getLocation();
		final ScrollBar vBar= getVerticalBar();
		if (vBar != null && vBar.isVisible()) {
			final int vSelection= vBar.getSelection();
			this.canvas.setLocation(location.x, -vSelection);
		}
	}
	
	
	protected void disconnect() {
		if (this.graphic != null) {
			this.graphic.removeListener(this);
		}
		locatorStopped();
	}
	
	public void setGraphic(final ERGraphic graphic) {
		disconnect();
		
		this.graphic= graphic;
		if (this.graphic != null) {
			this.graphic.addListener(this);
		}
		
		instructionsChanged(true, null);
		
		if (this.graphic != null && this.graphic.isLocatorStarted()) {
			locatorStarted();
		}
	}
	
	/**
	 * {@inheritDoc}
	 * <p>
	 * Note: No Layout can be set on this Control because it already
	 * manages the size and position of its children.</p>
	 */
	@Override
	public void setLayout (final Layout layout) {
		checkWidget();
		return;
	}
	
	@Override
	public void activated() {
	}
	
	@Override
	public void deactivated() {
	}
	
	@Override
	public void drawingStarted() {
	}
	
	@Override
	public void instructionsChanged(final boolean reset, final List<ERGraphicInstruction> added) {
		this.changedContent= true;
		if (isVisible()) {
			updateGraphic();
		}
	}
	
	@Override
	public void drawingStopped() {
	}
	
	@Override
	public void locatorStarted() {
		if (this.locatorListener == null) {
			this.locatorListener= new MouseListener() {
				@Override
				public void mouseDown(final MouseEvent e) {
					switch (e.button) { 
					case 1:
						RGraphicComposite.this.graphic.returnLocator(
								RGraphicComposite.this.canvas.widget2graphicsX(e.x), RGraphicComposite.this.canvas.widget2graphicY(e.y));
						break;
					case 3:
						RGraphicComposite.this.graphic.stopLocator(ERGraphic.LOCATOR_DONE);
						break;
					default:
						break;
					}
				}
				@Override
				public void mouseUp(final MouseEvent e) {
				}
				@Override
				public void mouseDoubleClick(final MouseEvent e) {
				}
			};
			this.canvas.addMouseListener(this.locatorListener);
			updateCursor();
		}
	}
	
	@Override
	public void locatorStopped() {
		if (this.locatorListener != null) {
			this.canvas.removeMouseListener(this.locatorListener);
			this.locatorListener= null;
			updateCursor();
		}
	}
	
	private void updateCursor() {
		if (this.panListener.started) {
			this.canvas.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_HAND));
		}
		else if (this.locatorListener != null) {
			this.canvas.setCursor(Display.getCurrent().getSystemCursor(SWT.CURSOR_CROSS));
		}
		else {
			this.canvas.setCursor(null);
		}
	}
	
	private void checkContentSize() {
		final Point size= this.canvas.computeSize(SWT.DEFAULT, SWT.DEFAULT);
		if (this.width == size.x && this.height == size.y) {
			return;
		}
		this.changedLayout= true;
		this.width= size.x;
		this.height= size.y;
		this.canvas.setSize(this.width, this.height);
		
		final ScrollBar hBar= getHorizontalBar();
		hBar.setMaximum(this.width);
		
		final ScrollBar vBar= getVerticalBar();
		vBar.setMaximum(this.height);
		layout(false);
	}
	
	
	public void redrawGraphic() {
		this.canvas.redraw();
	}
	
	private void updateGraphic() {
		this.changedContent= false;
		final List<? extends ERGraphicInstruction> instructions= (this.graphic != null) ?
				this.graphic.getInstructions() : RGraphicCanvas.NO_GRAPHIC;
		this.canvas.setInstructions(instructions);
		checkContentSize();
		this.canvas.redraw();
	}
	
	public double[] getGraphicFitSize() {
		final Rectangle bounds= getBounds();
		return new double[] { bounds.width, bounds.height };
	}
	
	public Control getControl() {
		return this;
	}
	
	/**
	 * Returns the control on which the graphic is painted
	 * 
	 * @since 1.0
	 */
	public Control getGraphicWidget() {
		return this.canvas;
	}
	
	/**
	 * Converts a horizontal display coordinate of the {@link #getGraphicWidget() graphic widget}
	 * to its graphic coordinate value.
	 * 
	 * @since 1.0
	 * @see ERGraphic Coordinate systems of R graphics
	 */
	public double convertWidget2GraphicX(final int x) {
		return this.canvas.widget2graphicsX(x);
	}
	
	/**
	 * Converts a vertical display coordinate of the {@link #getGraphicWidget() graphic widget}
	 * to its graphic coordinate value.
	 * 
	 * @since 1.0
	 * @see ERGraphic Coordinate systems of R graphics
	 */
	public double convertWidget2GraphicY(final int y) {
		return this.canvas.widget2graphicY(y);
	}
	
}
