/*******************************************************************************
 * Copyright (c) 2011 Laurent CARON
 * 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:
 *     Laurent CARON (laurent.caron at gmail dot com) - Initial implementation and API
 *******************************************************************************/
package org.mihalis.opal.imageSelector;

import java.io.File;
import java.io.FilenameFilter;
import java.io.IOException;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

import org.eclipse.core.runtime.FileLocator;
import org.eclipse.osbp.utils.themes.ui.VaaclipseUiTheme;
import org.eclipse.osbp.utils.themes.ui.VaaclipseUiTheme.ThemeList;
import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.MouseAdapter;
import org.eclipse.swt.events.MouseEvent;
import org.eclipse.swt.events.MouseMoveListener;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Font;
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.widgets.Canvas;
import org.eclipse.swt.widgets.Composite;
import org.eclipse.swt.widgets.Event;
import org.eclipse.swt.widgets.Listener;
import org.mihalis.opal.utils.SWTGraphicUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Instances of this class are controls that allow the user to select images.
 * <dl>
 * <dt><b>Styles:</b></dt>
 * <dd>(none)</dd>
 * <dt><b>Events:</b></dt>
 * <dd>(none)</dd>
 * </dl>
 * Work inspired by Romain Guy's work
 * (http://www.curious-creature.org/2005/07/09/a-music-shelf-in-java2d/)
 */
public class ImageSelector extends Canvas {
	
	/** The items. */
	private List<ISItem> items;
	
	/** The original items. */
	private List<ISItem> originalItems;
	
	/** The font. */
	private Font font;
	
	/** The Constant DEFAULT_WIDTH. */
	private static final int DEFAULT_WIDTH = 148;

	public static final int WIDTH_FACTOR = 3;
	
	/** The max item width. */
	private int maxItemWidth = DEFAULT_WIDTH;
	
	/** The index. */
	private int index = -1;
	
	/** The sigma. */
	private double sigma;
	
	/** The rho. */
	private double rho;
	
	/** The exp multiplier. */
	private double expMultiplier;
	
	/** The exp member. */
	private double expMember;
	
	/** The spacing. */
	private float spacing = 0.4f;
	
	/** The gradient start. */
	private Color gradientStart;
	
	/** The gradient end. */
	private Color gradientEnd;
	
	/** The animation step. */
	private double animationStep = -1d;
	
	/** The Constant TIMER_INTERVAL. */
	private static final int TIMER_INTERVAL = 50;
	
	/** The page increment. */
	private int pageIncrement = 5;

	/** The cached image. */
	private Image cachedImage;
	
	/** The cached gc. */
	private GC cachedGC;

	private String imagePlatformPath;

	private String imageName;

	// to avoid stupid actions from xtext
	boolean firstAction = true;

	/** The Constant LOGGER. */
	private static final Logger LOGGER = LoggerFactory.getLogger( ImageSelector.class );

	/**
	 * Constructs a new instance of this class given its parent and a style
	 * value describing its behavior and appearance.
	 * <p>
	 * The style value is either one of the style constants defined in class
	 * <code>SWT</code> which is applicable to instances of this class, or must
	 * be built by <em>bitwise OR</em>'ing together (that is, using the
	 * <code>int</code> "|" operator) two or more of those <code>SWT</code>
	 * style constants. The class description lists the style constants that are
	 * applicable to the class. Style bits are also inherited from superclasses.
	 * </p>
	 *
	 * @param parent a composite control which will be the parent of the new
	 *            instance (cannot be null)
	 * @param style the style of control to construct
	 *
	 * @exception IllegalArgumentException
	 *                <ul>
	 *                <li>ERROR_NULL_ARGUMENT - if the parent is null</li>
	 *                </ul>
	 * @exception SWTException
	 *                <ul>
	 *                <li>ERROR_THREAD_INVALID_ACCESS - if not called from the
	 *                thread that created the parent</li>
	 *                </ul>
	 *
	 */
	public ImageSelector(final Composite parent, final int style, final int defaultWidth) {
		super(parent, style | SWT.NO_BACKGROUND | SWT.DOUBLE_BUFFERED);
		final Font defaultFont = new Font(getDisplay(), "Lucida Sans", 24, SWT.NONE);
		font = defaultFont;
		SWTGraphicUtil.addDisposer(this, defaultFont);
		
		maxItemWidth = defaultWidth * WIDTH_FACTOR;

		setSigma(0.5);
		gradientStart = getDisplay().getSystemColor(SWT.COLOR_BLACK);
		gradientEnd = SWTGraphicUtil.getDefaultColor(this, 110, 110, 110);

		addListeners();
		SWTGraphicUtil.addDisposer(this, cachedGC);
		SWTGraphicUtil.addDisposer(this, cachedImage);
	}

	/**
	 * Adds the listeners.
	 */
	private void addListeners() {
		addKeyListener();
		addMouseListeners();

		addPaintListener(new PaintListener() {
			@Override
			public void paintControl(final PaintEvent e) {
				ImageSelector.this.paintControl(e);
			}
		});

		addListener(SWT.Resize, new Listener() {
			@Override
			public void handleEvent(final Event event) {
				if (cachedGC == null) {
					return;
				}
				cachedGC.dispose();
				cachedImage.dispose();
				cachedImage = new Image(getDisplay(), getClientArea());
				cachedGC = new GC(cachedImage);
				cachedGC.setAntialias(SWT.ON);
			}
		});
	}

	/**
	 * Add the key listener.
	 */
	private void addKeyListener() {
		this.addKeyListener(new KeyAdapter() {
			/**
			 * @see org.eclipse.swt.events.KeyAdapter#keyReleased(org.eclipse.swt.events.KeyEvent)
			 */
			@Override
			public void keyReleased(final KeyEvent e) {
				switch (e.keyCode) {
				case SWT.ARROW_LEFT:
				case SWT.ARROW_UP:
					scrollAndAnimateBy(-1);
					break;
				case SWT.ARROW_RIGHT:
				case SWT.ARROW_DOWN:
					scrollAndAnimateBy(1);
					break;
				case SWT.HOME:
					scrollBy(-1 * ImageSelector.this.index);
					break;
				case SWT.END:
					scrollBy(ImageSelector.this.index);
					break;
				case SWT.PAGE_UP:
					scrollBy(-1 * ImageSelector.this.pageIncrement);
					break;
				case SWT.PAGE_DOWN:
					scrollBy(ImageSelector.this.pageIncrement);
					break;
				case SWT.KEYPAD_CR:
				case SWT.CR:
					if (!firstAction) {
						selectImage();
					}
					break;
				default: scrollToItem(Character.toString(e.character));
				}
				firstAction = false;
			}
		});
	}

	/**
	 * Add mouse listeners.
	 */
	private void addMouseListeners() {
		addMouseMoveListener(new MouseMoveListener() {
			@Override
			public void mouseMove(final MouseEvent e) {
				for (final ISItem item : items) {
					if (item.getUpperLeftCorner() != null && item.getLowerRightCorner() != null && e.x >= item.getUpperLeftCorner().x && e.x <= item.getLowerRightCorner().x && e.y >= item.getUpperLeftCorner().y
							&& e.y <= item.getLowerRightCorner().y) {
						setCursor(getDisplay().getSystemCursor(SWT.CURSOR_HAND));
						return;
					}
				}
				setCursor(getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
			}
		});

		addMouseListener(new MouseAdapter() {
			/**
			 * @see org.eclipse.swt.events.MouseAdapter#mouseUp(org.eclipse.swt.events.MouseEvent)
			 */
			@Override
			public void mouseUp(final MouseEvent e) {
				for (final ISItem item : items) {
					if (item.getUpperLeftCorner() != null && item.getLowerRightCorner() != null && e.x >= item.getUpperLeftCorner().x && e.x <= item.getLowerRightCorner().x && e.y >= item.getUpperLeftCorner().y
							&& e.y <= item.getLowerRightCorner().y) {
						scrollAndAnimateBy(originalItems.indexOf(item) - index);
						return;
					}
				}
			}
		});

		addListener(SWT.MouseWheel, new Listener() {
			@Override
			public void handleEvent(final Event event) {
				scrollBy(-1 * event.count);
			}
		});
	}

	/**
	 * Set the sigma value for the gaussian curve.
	 *
	 * @param sigma new sigma parameter
	 */
	public void setSigma(final double sigma) {
		this.sigma = sigma;
		rho = 1.0;
		computeEquationParts();
		rho = computeModifierUnbounded(0.0);
		computeEquationParts();
		redraw();
	}

	/**
	 * Compute the value of the modifier. The value is bounded between -1 and +1
	 *
	 * @param x input value
	 * @return the value of the modifier between -1 and +1
	 */
	private double computeModifierBounded(final double x) {
		double result = computeModifierUnbounded(x);
		if (result > 1.0) {
			result = 1.0;
		} else if (result < -1.0) {
			result = -1.0;
		}
		return result;
	}

	/**
	 * Compute the value of the modifier.
	 *
	 * @param x input value
	 * @return the value of the function
	 */
	private double computeModifierUnbounded(final double x) {
		return expMultiplier * Math.exp(-x * x / expMember);
	}

	/**
	 * Computer both members of the equation.
	 */
	private void computeEquationParts() {
		expMultiplier = Math.sqrt(2.0 * Math.PI) / sigma / rho;
		expMember = 4.0 * sigma * sigma;
	}

	/**
	 * Draw the widget.
	 *
	 * @param e the paintEvent
	 */
	private void paintControl(final PaintEvent e) {

		if (cachedImage == null) {
			cachedImage = new Image(getDisplay(), getClientArea());
			cachedGC = new GC(cachedImage);
			cachedGC.setAntialias(SWT.ON);
		}

		// Draw gradient
		drawBackground();

		// Draw the items
		drawItems();

		// Draw the title
		if (animationStep < 0d) {
			drawTitle();
		}

		// Draw the offscreen buffer to the screen
		e.gc.drawImage(cachedImage, 0, 0);
		
		cachedGC.dispose();
		cachedImage.dispose();
		cachedImage = null;
	}

	/**
	 * Draw the background.
	 */
	private void drawBackground() {
		final Rectangle rect = getClientArea();

		cachedGC.setForeground(gradientStart);
		cachedGC.setBackground(gradientEnd);
		cachedGC.fillGradientRectangle(rect.x, rect.y, rect.width, rect.height / 2, true);

		cachedGC.setForeground(gradientEnd);
		cachedGC.setBackground(gradientStart);
		cachedGC.fillGradientRectangle(rect.x, rect.height / 2, rect.width, rect.height / 2, true);
	}

	/**
	 * Draw the items.
	 */
	private void drawItems() {
		if (animationStep < 0d) {
			items.clear();
			items.addAll(originalItems);
			for (int i = 0; i < items.size(); i++) {
				final ISItem item = items.get(i);
				item.setzPosition((i - index) * spacing);
			}
			Collections.sort(items);
		}

		for (final ISItem item : items) {
			drawItem(item);
		}
	}

	/**
	 * Draw a given item.
	 *
	 * @param item item to draw
	 */
	private void drawItem(final ISItem item) {

		final int size = computeSize(item);
		final int centerX = computeZPosition(item);
		final int centerY = getClientArea().height / 2;

		if (size <= 0 || centerX < 0 || centerX > getBounds().width) {
			item.resetCornerToNull();
			return;
		}

		final int alpha = computeAlpha(item);

		final Image newImage = SWTGraphicUtil.createReflectedResizedImage(item.getImage(), size, size);
		cachedGC.setAlpha(alpha);

		final int x = centerX - newImage.getBounds().width / 2;
		final int y = centerY - newImage.getBounds().height / 2;

		cachedGC.drawImage(newImage, x, y);

		item.setUpperLeftCorner(x, y);
		item.setLowerRightCorner(x + newImage.getBounds().width, (int) (y + newImage.getBounds().height / 1.5));

		newImage.dispose();
	}

	/**
	 * Compute the z position for a given item.
	 *
	 * @param item item
	 * @return the z position of the item
	 */
	private int computeZPosition(final ISItem item) {
		final int totalWidth = getClientArea().width / 2;
		final int centerX = getClientArea().width / 2;
		return (int) (centerX + item.getzPosition() * totalWidth);
	}

	/**
	 * Compute size for a given item.
	 *
	 * @param item item
	 * @return the size of the item
	 */
	private int computeSize(final ISItem item) {
		return (int) (computeModifierBounded(item.getzPosition()) * maxItemWidth);
	}

	/**
	 * Compute the alpha value of a given item.
	 *
	 * @param item item
	 * @return the alpha value of the item
	 */
	private int computeAlpha(final ISItem item) {
		return (int) (255 - 150 * Math.abs(item.getzPosition()));
	}

	/**
	 * Draw the title under the selected item.
	 */
	private void drawTitle() {
		final String title = originalItems.get(index).getText();
		if (title == null || title.trim().equals("")) {
			return;
		}
		cachedGC.setFont(getFont());
		final Point textSize = cachedGC.stringExtent(title);

		cachedGC.setFont(getFont());
		cachedGC.setForeground(getDisplay().getSystemColor(SWT.COLOR_WHITE));
		cachedGC.setAlpha(255);

		final int centerX = getClientArea().width / 2;
		final int centerY = (getClientArea().height + maxItemWidth) / 2;

		cachedGC.drawString(title, centerX - textSize.x / 2, centerY - textSize.y / 2, true);

	}

	/**
	 * Scroll the selected item.
	 *
	 * @param increment increment value
	 */
	private void scrollBy(final int increment) {
		index += increment;
		if (index < 0) {
			index = 0;
		}

		if (index >= items.size()) {
			index = items.size() - 1;
		}
		redraw();
	}

	/**
	 * Scroll the selected item with an animation.
	 *
	 * @param increment increment value
	 */
	private void scrollAndAnimateBy(final int increment) {
		if (increment == 0 || index == 0 && increment < 0 || index == items.size() - 1 && increment > 0) {
			return;
		}

		final double step = Math.abs(increment) / (300d / TIMER_INTERVAL);
		ImageSelector.this.animationStep = step;
		setCursor(getDisplay().getSystemCursor(SWT.CURSOR_WAIT));

		getDisplay().syncExec(new Runnable() {

			@Override
			public void run() {
				startAnimation(increment, step);
			}

			private void startAnimation(final int increment, final double step) {
				items.clear();
				items.addAll(originalItems);
				for (int i = 0; i < items.size(); i++) {
					final ISItem item = items.get(i);
					item.setzPosition((i - index + animationStep * (increment > 0 ? -1d : 1d)) * spacing);
				}
				Collections.sort(items);
				if (!isDisposed()) {
					redraw();
				}

				animationStep += step;
				if (animationStep >= 1d) {
					animationStep = -1d;
					index += increment;
					setCursor(getDisplay().getSystemCursor(SWT.CURSOR_ARROW));
				} else {
					if (!isDisposed()) {
						getDisplay().timerExec(TIMER_INTERVAL, this);
					}
				}
			}
		});

	}

	
	/**
	 * Scrolls to an item in {@link #items} whose name
	 * starts with the given prefix.
	 * @param prefix the prefix
	 */
	private void scrollToItem(String prefix){
		int idx = findIndexOfFirstItemWithStartingName(prefix);
		if(idx != -1) {
			this.index = idx;
			redraw();
		}
	}
	
	/**
	 * Returns the index of the first item element whose names
	 * starts with the given prefix. 
	 * @param prefix the prefix
	 * @return the item index or -1 if none is found
	 */
	private int findIndexOfFirstItemWithStartingName(String prefix){
		for(ISItem item : ImageSelector.this.items){
			if(item.getText().startsWith(prefix)){
				return ImageSelector.this.items.indexOf(item);
			}
		}
		return -1;
	}

	/**
	 * Gets the items.
	 *
	 * @return the items displayed by this widget
	 */
	public List<ISItem> getItems() {
		return originalItems;
	}

	/**
	 * Sets the items.
	 *
	 * @param items the items that are displayed in this widget to set
	 */
	public void setItems(final List<ISItem> items) {
		this.items = new ArrayList<ISItem>(items);
		originalItems = items;
		index = this.items.size() / 2;
		redraw();
	}

	/**
	 * Sets the items.
	 *
	 * @param filterExtensions
	 *            the new items
	 */
	public void setItems(final String [] filterExtensions) {
		// Create the list of images
		final List<ISItem> items = new LinkedList<ISItem>();
		URI iconsUri = null;
		Set<VaaclipseUiTheme> themes = VaaclipseUiTheme.values(ThemeList.forProduct);
		for (VaaclipseUiTheme vaaclipseUiTheme : themes) {
			if(vaaclipseUiTheme.hasIconsUri()) {
				iconsUri = vaaclipseUiTheme.getIconsUri();
				break;
			}
		}
		if(iconsUri == null) {
			LOGGER.error("no theme provider bundle found");
			return;
		}
		try {
			File pathFolder = new File(FileLocator.toFileURL(iconsUri.toURL()).getPath());
			if (pathFolder.isDirectory()) {
				File[] imgFiles = pathFolder.listFiles(new FilenameFilter() {
					public boolean accept(File dir, String filename) {
						for (int i = 0; i < filterExtensions.length; i++) {
							boolean fileNameFound = filename.endsWith(filterExtensions[i]);
							if (fileNameFound) return fileNameFound;
						}
						return false;
					}
				});
				if	( imgFiles != null ) {
					for (File imgFile : imgFiles) {
						items.add( new ISItem(imgFile));
					}
				}
			}
			setItems(items);
		} catch (IOException e) {
			LOGGER.error(e.getLocalizedMessage()+e.getCause().getLocalizedMessage());
		}
	}

	/**
	 * Disposes all SWT-items within CCISItem-list {@literal}items. Clears list
	 * afterwards.
	 *
	 * @return void
	 */
	public void clearItems () {
		for ( ISItem item : this.items ) {
			item.dispose();
		}
		this.items.clear();
	}

	/**
	 * Gets the font.
	 *
	 * @return the font used for the title
	 */
	@Override
	public Font getFont() {
		return font;
	}

	/**
	 * Sets the font.
	 *
	 * @param font the font used for the title to set
	 */
	@Override
	public void setFont(final Font font) {
		this.font = font;
		redraw();
	}

	/**
	 * Gets the index.
	 *
	 * @return the index of the selected image
	 */
	public int getIndex() {
		return index;
	}

	/**
	 * Sets the index.
	 *
	 * @param index the index of the selected image to set
	 */
	public void setIndex(final int index) {
		this.index = index;
		redraw();
	}

	/**
	 * Gets the max item width.
	 *
	 * @return the maximum items width
	 */
	public int getMaxItemWidth() {
		return maxItemWidth;
	}

	/**
	 * Sets the max item width.
	 *
	 * @param maxItemWidth the the maximum items width to set
	 */
	public void setMaxItemWidth(final int maxItemWidth) {
		this.maxItemWidth = maxItemWidth;
		redraw();
	}

	/**
	 * Gets the sigma.
	 *
	 * @return the sigma value
	 */
	public double getSigma() {
		return sigma;
	}

	/**
	 * Gets the spacing.
	 *
	 * @return the spacing between 2 items
	 */
	public float getSpacing() {
		return spacing;
	}

	/**
	 * Sets the spacing.
	 *
	 * @param spacing the the spacing between 2 items to set
	 */
	public void setSpacing(final float spacing) {
		this.spacing = spacing;
		redraw();
	}

	/**
	 * Gets the gradient start.
	 *
	 * @return the gradient start color
	 */
	public Color getGradientStart() {
		return gradientStart;
	}

	/**
	 * Sets the gradient start.
	 *
	 * @param gradientStart the the gradient start color to set
	 */
	public void setGradientStart(final Color gradientStart) {
		this.gradientStart = gradientStart;
		redraw();
	}

	/**
	 * Gets the gradient end.
	 *
	 * @return the the gradient end color
	 */
	public Color getGradientEnd() {
		return gradientEnd;
	}

	/**
	 * Sets the gradient end.
	 *
	 * @param gradientEnd the the gradient end color to set
	 */
	public void setGradientEnd(final Color gradientEnd) {
		this.gradientEnd = gradientEnd;
		redraw();
	}

	/**
	 * Gets the page increment.
	 *
	 * @return the page increment when the user uses PgUp and PgDown
	 */
	public int getPageIncrement() {
		return pageIncrement;
	}

	/**
	 * Sets the page increment.
	 *
	 * @param pageIncrement the page increment to set
	 */
	public void setPageIncrement(final int pageIncrement) {
		this.pageIncrement = pageIncrement;
	}

	/**
	 * Select image.
	 */
	private void selectImage() {
		int idx = ImageSelector.this.index;

		try {
			ISItem isItem = ImageSelector.this.originalItems.get(idx);
			imagePlatformPath = isItem.getUrl().toString();
			imageName = isItem.getText();
			getParent().dispose();
		} catch (IndexOutOfBoundsException e) {
			// do nothing
			e.printStackTrace();	// NOSONAR
			LOGGER.warn( String.format( "selectImage(): no index %d in originalItems", idx ), e );
		}
	}
	
	/**
	 * Gets the image platform path.
	 *
	 * @return the image platform path
	 */
	public String getImagePlatformPath() {
		return imagePlatformPath;
	}

	/**
	 * Gets the image name.
	 *
	 * @return the image name
	 */
	public String getImageName() {
		return imageName;
	}
}
