/*****************************************************************************
 * Copyright (c) 2004 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.wst.xml.ui.internal.tabletree;

import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import org.eclipse.jface.viewers.CellEditor;
import org.eclipse.jface.viewers.ICellEditorListener;
import org.eclipse.jface.viewers.ICellModifier;
import org.eclipse.swt.SWT;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.KeyAdapter;
import org.eclipse.swt.events.KeyEvent;
import org.eclipse.swt.events.KeyListener;
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.events.SelectionEvent;
import org.eclipse.swt.events.SelectionListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.Cursor;
import org.eclipse.swt.graphics.GC;
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.ScrollBar;
import org.eclipse.swt.widgets.Text;
import org.eclipse.swt.widgets.Tree;
import org.eclipse.swt.widgets.TreeItem;
import org.eclipse.ui.PlatformUI;


public class TreeExtension implements PaintListener {

	protected Tree fTree;
	protected EditManager editManager;
	protected String[] fColumnProperties;
	protected ICellModifier cellModifier;
	protected int columnPosition = 300;
	protected int columnHitWidth = 5;
	protected Color tableLineColor;
	protected int controlWidth;
	protected DelayedDrawTimer delayedDrawTimer;
	private boolean fisUnsupportedInput = false;

	public TreeExtension(Tree tree) {
		this.fTree = tree;
		InternalMouseListener listener = new InternalMouseListener();
		tree.addMouseMoveListener(listener);
		tree.addMouseListener(listener);
		tree.addPaintListener(this);
		editManager = new EditManager(tree);
		delayedDrawTimer = new DelayedDrawTimer(tree);

		tableLineColor = tree.getDisplay().getSystemColor(SWT.COLOR_WIDGET_LIGHT_SHADOW);
	}

	public void dispose() {
		tableLineColor.dispose();
	}

	public void setCellModifier(ICellModifier modifier) {
		cellModifier = modifier;
	}

	public void resetCachedData() {
		// todo: sure seems we should reset something?
	}

	public ICellModifier getCellModifier() {
		return cellModifier;
	}

	public List getItemList() {
		List list = new Vector();
		getItemListHelper(fTree.getItems(), list);
		return list;
	}

	protected void getItemListHelper(TreeItem[] items, List list) {
		for (int i = 0; i < items.length; i++) {
			TreeItem item = items[i];
			list.add(item);
			getItemListHelper(item.getItems(), list);
		}
	}

	protected TreeItem getTreeItemOnRow(int px, int py) {
		TreeItem result = null;
		List list = getItemList();
		for (Iterator i = list.iterator(); i.hasNext();) {
			TreeItem item = (TreeItem) i.next();
			Rectangle r = item.getBounds();
			if (r != null && px >= r.x && py >= r.y && py <= r.y + r.height) {
				result = item;
			}
		}
		return result;
	}

	protected class InternalMouseListener extends MouseAdapter implements MouseMoveListener {
		protected int columnDragged = -1;
		protected boolean isDown = false;
		protected int prevX = -1;
		protected Cursor cursor = null;

		public void mouseMove(MouseEvent e) {
			if (e.x > columnPosition - columnHitWidth && e.x < columnPosition + columnHitWidth) {
				if (cursor == null) {
					cursor = new Cursor(fTree.getDisplay(), SWT.CURSOR_SIZEWE);
					fTree.setCursor(cursor);
				}
			}
			else {
				if (cursor != null) {
					fTree.setCursor(null);
					cursor.dispose();
					cursor = null;
				}
			}

			if (columnDragged != -1) {
				// using the delay timer will make redraws less flickery
				if (e.x > 20) {
					columnPosition = e.x;
					delayedDrawTimer.reset(20);
				}
			}
		}

		public void mouseDown(MouseEvent e) {
			// here we handle the column resizing by detect if the user has
			// click on a column separator
			//
			columnDragged = -1;
			editManager.deactivateCellEditor();

			if (e.x > columnPosition - columnHitWidth && e.x < columnPosition + columnHitWidth) {
				columnDragged = 0;
			}

			// here we handle selecting tree items when any thing on the 'row'
			// is clicked
			//
			TreeItem item = fTree.getItem(new Point(e.x, e.y));
			if (item == null) {
				item = getTreeItemOnRow(e.x, e.y);
				if (item != null) {
					TreeItem[] items = new TreeItem[1];
					items[0] = item;
					fTree.setSelection(items);
				}
			}
		}

		public void mouseUp(MouseEvent e) {
			columnDragged = -1;
		}
	}

	public String[] getColumnProperties() {
		return fColumnProperties;
	}

	public void setColumnProperties(String[] columnProperties) {
		this.fColumnProperties = columnProperties;
	}

	public void paintControl(PaintEvent event) {
		GC gc = event.gc;
		Rectangle treeBounds = fTree.getBounds();

		controlWidth = treeBounds.width;
		Color bg = fTree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND);
		Color bg2 = fTree.getDisplay().getSystemColor(SWT.COLOR_LIST_SELECTION);

		gc.setBackground(bg2);

		// // This next part causes problems on LINUX, so let's not do it
		// there
		// if (B2BHacks.IS_UNIX == false) {
		// TreeItem[] selectedItems = tree.getSelection();
		// if (selectedItems.length > 0) {
		// for (int i = 0; i < selectedItems.length; i++) {
		// TreeItem item = selectedItems[i];
		// Rectangle bounds = item.getBounds();
		// if (bounds != null) {
		// gc.fillRectangle(bounds.x + bounds.width, bounds.y, controlWidth,
		// bounds.height);
		// }
		// }
		// }
		// }
		//
		if (!fisUnsupportedInput) {
			TreeItem[] items = fTree.getItems();
			if (items.length > 0) {
				gc.setForeground(tableLineColor);
				gc.setBackground(bg);

				gc.fillRectangle(columnPosition, treeBounds.x, treeBounds.width, treeBounds.height);

				Rectangle itemBounds = items[0].getBounds();
				int height = computeTreeItemHeight();

				if (itemBounds != null) {
					/*
					 * Bounds will be for the first item, which will either be
					 * visible at the top of the Tree, or scrolled off with
					 * negative values
					 */
					int startY = itemBounds.y;

					/* Only draw lines within the Tree boundaries */
					for (int i = startY; i < treeBounds.height; i += height) {
						if (i >= treeBounds.y) {
							gc.drawLine(0, i, treeBounds.width, i);
						}
					}
				}
				gc.drawLine(columnPosition, 0, columnPosition, treeBounds.height);
				paintItems(gc, items, treeBounds);

			}
			else {
				addEmptyTreeMessage(gc);
			}
		}
		else {
			addUnableToPopulateTreeMessage(gc);
		}
	}

	protected int computeTreeItemHeight() {
		int result = -1;

		/*
		 * On GTK tree.getItemHeight() seems to lie to us. It reports that the
		 * tree item occupies a few pixles less vertical space than it should
		 * (possibly because of the image height vs. the text height?). This
		 * foils our code that draws the 'row' lines since we assume that
		 * lines should be drawn at 'itemHeight' increments. Don't trust
		 * getItemHeight() to compute the increment... instead compute the
		 * value based on distance between two TreeItems, and then use the
		 * larger value.
		 * 
		 * This strategy only works on trees where the items are of even
		 * height, however bug
		 * https://bugs.eclipse.org/bugs/show_bug.cgi?id=117201 indicates that
		 * this is no longer promised, at least on win32 and likely on other
		 * platforms soon.
		 */
		if (fTree.getItemCount() > 0) {
			TreeItem[] items = fTree.getItems();
			Rectangle itemBounds = items[0].getBounds();

			if (items[0].getExpanded()) {
				TreeItem[] children = items[0].getItems();
				if (children.length > 0) {
					result = children[0].getBounds().y - itemBounds.y;
				}
			}
			else if (items.length > 1) {
				result = items[1].getBounds().y - itemBounds.y;
			}
		}

		result = Math.max(fTree.getItemHeight(), result);
		return result;
	}

	protected void addEmptyTreeMessage(GC gc) {
		// nothing to add here
	}

	private void addUnableToPopulateTreeMessage(GC gc) {
		// here we print a message when the document cannot be displayed just
		// to give the
		// user a visual cue
		// so that they know how to proceed to edit the blank view
		gc.setForeground(fTree.getDisplay().getSystemColor(SWT.COLOR_BLACK));
		gc.setBackground(fTree.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
		gc.drawString(XMLEditorMessages.TreeExtension_0, 10, 10);
	}

	void setIsUnsupportedInput(boolean isUnsupported) {
		fisUnsupportedInput = isUnsupported;
	}

	public void paintItems(GC gc, TreeItem[] items, Rectangle treeBounds) {
		if (items != null) {
			for (int i = 0; i < items.length; i++) {
				TreeItem item = items[i];
				if (item != null) {
					Rectangle bounds = item.getBounds();
					if (bounds != null) {
						if (treeBounds.intersects(bounds)) {
							paintItem(gc, item, bounds);
						}
					}

					// defect 241039
					//
					if (item.getExpanded()) {
						paintItems(gc, item.getItems(), treeBounds);
					}
				}
			}
		}
	}

	protected void paintItem(GC gc, TreeItem item, Rectangle bounds) {
		// nothing to paint
	}

	public interface ICellEditorProvider {
		CellEditor getCellEditor(Object o, int col);
	}

	/**
	 * This class is used to improve drawing during a column resize.
	 */
	public class DelayedDrawTimer implements Runnable {
		protected Control control;

		public DelayedDrawTimer(Control control1) {
			this.control = control1;
		}

		public void reset(int milliseconds) {
			getDisplay().timerExec(milliseconds, this);
		}

		public void run() {
			control.redraw();
		}
	}

	Display getDisplay() {

		return PlatformUI.getWorkbench().getDisplay();
	}

	/**
	 * EditManager
	 */
	public class EditManager {
		protected Tree fTree1;
		protected Control cellEditorHolder;
		protected CellEditorState cellEditorState;

		public EditManager(Tree tree) {
			this.fTree1 = tree;
			this.cellEditorHolder = new Composite(tree, SWT.NONE);

			final Tree theTree = tree;

			MouseAdapter theMouseAdapter = new MouseAdapter() {
				public void mouseDown(MouseEvent e) {
					deactivateCellEditor();

					if (e.x > columnPosition + columnHitWidth) {
						TreeItem[] items = theTree.getSelection();
						// No edit if more than one row is selected.
						if (items.length == 1) {
							Rectangle bounds = items[0].getBounds();
							if (bounds != null && e.y >= bounds.y && e.y <= bounds.y + bounds.height) {
								int columnToEdit = 1;
								activateCellEditor(items[0], columnToEdit);
							}
						}
					}
				}
			};

			SelectionListener selectionListener = new SelectionListener() {
				public void widgetDefaultSelected(SelectionEvent e) {
					applyCellEditorValue();
				}

				public void widgetSelected(SelectionEvent e) {
					applyCellEditorValue();
				}
			};

			KeyListener keyListener = new KeyAdapter() {
				public void keyPressed(KeyEvent e) {
					if (e.character == SWT.CR) {
						deactivateCellEditor();
						TreeItem[] items = theTree.getSelection();
						if (items.length == 1) {
							activateCellEditor(items[0], 1);
						}
					}
				}
			};

			tree.addMouseListener(theMouseAdapter);
			tree.addKeyListener(keyListener);
			ScrollBar hBar = tree.getHorizontalBar();
			if (hBar != null)
				hBar.addSelectionListener(selectionListener);
			ScrollBar vBar = tree.getVerticalBar();
			if (vBar != null)
				vBar.addSelectionListener(selectionListener);
		}

		public boolean isCellEditorActive() {
			return cellEditorState != null;
		}

		public void applyCellEditorValue() {
			if (cellEditorState != null && cellModifier != null) {
				TreeItem treeItem = cellEditorState.fTreeItem;

				// The area below the cell editor needs to be explicity
				// repainted on Linux
				//
				// Rectangle r = B2BHacks.IS_UNIX ? treeItem.getBounds() :
				// null;

				Object value = cellEditorState.fCellEditor.getValue();
				String property = cellEditorState.fProperty;

				deactivateCellEditor();

				cellModifier.modify(treeItem, property, value);

				// if (r != null) {
				// tree.redraw(r.x, r.y, tree.getBounds().width, r.height,
				// false);
				// }
			}
		}

		public void deactivateCellEditor() {
			// Clean up any previous editor control
			if (cellEditorState != null) {
				cellEditorState.deactivate();
				cellEditorState = null;
			}
		}

		public void activateCellEditor(TreeItem treeItem, int column) {
			if (cellModifier instanceof ICellEditorProvider) {
				ICellEditorProvider cellEditorProvider = (ICellEditorProvider) cellModifier;
				Object data = treeItem.getData();
				if (fColumnProperties.length > column) {
					String property = fColumnProperties[column];
					if (cellModifier.canModify(data, property)) {
						CellEditor newCellEditor = cellEditorProvider.getCellEditor(data, column);
						if (newCellEditor != null) {
							// The control that will be the editor must be a
							// child of the columnPosition
							Control control = newCellEditor.getControl();
							if (control != null) {
								cellEditorState = new CellEditorState(newCellEditor, control, treeItem, column, property);
								cellEditorState.activate();
							}
						}
					}
				}
			}
		}

		/**
		 * this class holds the state that is need on a per cell editor
		 * invocation basis
		 */
		public class CellEditorState implements ICellEditorListener, FocusListener {
			public CellEditor fCellEditor;
			public Control fControl;
			public TreeItem fTreeItem;
			public int fColumnNumber;
			public String fProperty;

			public CellEditorState(CellEditor cellEditor, Control control, TreeItem treeItem, int columnNumber, String property) {
				this.fCellEditor = cellEditor;
				this.fControl = control;
				this.fTreeItem = treeItem;
				this.fColumnNumber = columnNumber;
				this.fProperty = property;
			}

			public void activate() {
				Object element = fTreeItem.getData();
				String value = cellModifier.getValue(element, fProperty).toString();
				if (fControl instanceof Text) {
					Text text = (Text) fControl;
					int requiredSize = value.length() + 100;
					if (text.getTextLimit() < requiredSize) {
						text.setTextLimit(requiredSize);
					}
				}
				Rectangle r = fTreeItem.getBounds();
				if (r != null) {
					fControl.setBounds(columnPosition + 5, r.y + 1, fTree1.getClientArea().width - (columnPosition + 5), r.height - 1);
					fControl.setVisible(true);
					fCellEditor.setValue(value);
					fCellEditor.addListener(this);
					fCellEditor.setFocus();
					fControl.addFocusListener(this);
				}
			}

			public void deactivate() {
				fCellEditor.removeListener(this);
				fControl.removeFocusListener(this);
				fCellEditor.deactivate();
				fTree1.forceFocus();
			}

			// ICellEditorListener methods
			//
			public void applyEditorValue() {
				applyCellEditorValue();
			}

			public void cancelEditor() {
				deactivateCellEditor();
			}

			public void editorValueChanged(boolean oldValidState, boolean newValidState) {
				// nothing, for now
			}

			// FocusListener methods
			//
			public void focusGained(FocusEvent e) {
				// do nothing
			}

			public void focusLost(FocusEvent e) {
				applyCellEditorValue();
			}
		}
	}
}