package jp.sourceforge.projects.ee2e.core.display;

import org.eclipse.swt.widgets.Composite;
import org.eclipse.ui.part.ViewPart;
import jp.sourceforge.projects.ee2e.core.*;

import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.*;
import org.eclipse.swt.widgets.*;
import org.eclipse.swt.events.*;
import org.eclipse.ui.*;

/**
 * To change this generated comment edit the template variable "typecomment":
 * Window&gt;Preferences&gt;Java&gt;Templates.
 * To enable and disable the creation of type comments go to
 * Window&gt;Preferences&gt;Java&gt;Code Generation.
 *
 * @author Toshikazu Ando [ ando@park.ruru.ne.jp ]
 */
public class EE2EMiniBufferView extends ViewPart {
	/**
	 * Constructor for EE2EMiniBufferView.
	 */
	public EE2EMiniBufferView() {
		super();
		EE2EDebug.printf(3, "EE2EMiniBufferView");
	}

	public static EE2EMiniBufferView showEE2EDisplayCompletion(EE2EDisplayCompletion completention) {
		IViewPart part = null;
        IWorkbenchPage page = getIWorkbenchPage();
        if(page == null) {
            return null;
        }
        try {
            part = page.showView(EE2EPlugin.MINI_BUFFER_VIEW_ID);
        } catch (PartInitException e) {
            EE2EDebug.printf(
                1,
                "not IViewPart id=" + EE2EPlugin.MINI_BUFFER_VIEW_ID);
        }
        if(part == null) {
			EE2EDebug.printf(1, "not part");
            return null;
        }
		if (!(part instanceof EE2EMiniBufferView)) {
			EE2EDebug.printf(1, "not EE2EMiniBufferView");
			return null;
		}
		EE2EMiniBufferView miniBufferView = (EE2EMiniBufferView) part;
		miniBufferView.setEE2EDisplayCompletion(completention);
		miniBufferView.setFocus();
		eE2EMiniBufferView = miniBufferView;
		return miniBufferView;
	}
	private static EE2EMiniBufferView eE2EMiniBufferView;
	public static void removeEE2EDisplayCompletion() {
		EE2EDebug.printf(3, "not removeEE2EDisplayCompletion");
		if (eE2EMiniBufferView != null) {
			EE2EDebug.printf(3, "dispose");
			eE2EMiniBufferView.dataClearAndDisable();
            IWorkbenchPage page = getIWorkbenchPage();
            if(page != null) {
                page.hideView(eE2EMiniBufferView);
            }
		}
	}
	protected static IWorkbenchPage getIWorkbenchPage() {
        EE2EPlugin plugin = EE2EPlugin.getDefault();
		if (plugin == null) {
			EE2EDebug.printf(1, "not EE2EPlugin");
			return null;
		}
		IWorkbench bentch = plugin.getWorkbench();
		if (bentch == null) {
			EE2EDebug.printf(1, "not IWorkbench");
			return null;
		}
		IWorkbenchWindow window = bentch.getActiveWorkbenchWindow();
		if (window == null) {
			EE2EDebug.printf(1, "not IWorkbenchWindow");
			return null;
		}
		IWorkbenchPage page = window.getActivePage();
		if (page == null) {
			EE2EDebug.printf(1, "not IWorkbenchPage");
			return null;
		}
		return page;
	}

	protected void setEE2EDisplayCompletion(EE2EDisplayCompletion completention) {
		EE2EDisplayCompletion work = this.completention;
		this.completention = completention;
		if (work != null) {
			work.dispose();
		}
		if (this.completention != null) {
            this.setTitle(this.completention.getTitleText());
			this.text.setText("");
			this.text.setEnabled(true);
			this.list.removeAll();
			this.list.setEnabled(true);
		}
	}

	/**
	 * @see org.eclipse.ui.IWorkbenchPart#createPartControl(Composite)
	 */
	public void createPartControl(Composite parent) {
		GridLayout layout = new GridLayout();
		layout.numColumns = 6;
        layout.marginHeight = 3;
        layout.marginWidth = 3;
        layout.horizontalSpacing = 3;
        layout.verticalSpacing = 3;
		layout.makeColumnsEqualWidth = true;
		parent.setLayout(layout);

        this.setTitle("start");

		this.text = new Text(parent, SWT.SINGLE | SWT.H_SCROLL);
		this.text.addKeyListener(this.keyListener);
        GridData grid1 = new GridData();
        grid1.horizontalAlignment = GridData.FILL;
        grid1.verticalAlignment = GridData.FILL;
        grid1.horizontalIndent = 1;
        grid1.horizontalSpan = layout.numColumns;
        grid1.verticalSpan = 1;
        grid1.grabExcessHorizontalSpace = true;
        grid1.grabExcessVerticalSpace = false;
        this.text.setLayoutData(grid1);
        //
		this.list =
			new org.eclipse.swt.widgets.List(
				parent,SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
		this.list.addSelectionListener(this.selectionListener);
        GridData grid2 = new GridData();
        grid2.horizontalAlignment = GridData.FILL;
        grid2.verticalAlignment = GridData.FILL;
        grid2.horizontalIndent = 1;
        grid2.horizontalSpan = layout.numColumns - 1;
        grid2.verticalSpan = 1;
        grid2.grabExcessHorizontalSpace = false;
        grid2.grabExcessVerticalSpace = true;
		this.list.setLayoutData(grid2);
        //
        this.tagList =
            new org.eclipse.swt.widgets.List(
                parent,SWT.MULTI | SWT.V_SCROLL | SWT.H_SCROLL);
        GridData grid3 = new GridData();
        grid3.horizontalAlignment = GridData.FILL;
        grid3.verticalAlignment = GridData.FILL;
        grid3.horizontalIndent = 1;
        grid3.horizontalSpan = 1;
        grid3.verticalSpan = 1;
        grid3.grabExcessHorizontalSpace = false;
        grid3.grabExcessVerticalSpace = true;
        this.tagList.setLayoutData(grid3);
        //
        this.text.setEnabled(false);
        this.list.setEnabled(false);
	}

	/**
	 * @see org.eclipse.ui.IWorkbenchPart#setFocus()
	 */
	public void setFocus() {
		this.text.setFocus();
	}

	private KeyListener keyListener = new KeyListener() {
		/**
		 * Sent when a key is pressed on the system keyboard.
		 *
		 * @param e an event containing information about the key press
		 */
		public void keyPressed(KeyEvent e) {
		}

		/**
		 * Sent when a key is released on the system keyboard.
		 *
		 * @param e an event containing information about the key release
		 */
		public void keyReleased(KeyEvent e) {
            int chInt = (int) e.character;
            if ((chInt == 7) && ((e.stateMask & SWT.CTRL) != 0)) {
                EE2EMiniBufferView.removeEE2EDisplayCompletion();
                return;
            } else if (
                    (e.character == ' ')
            && ((e.stateMask & SWT.CTRL) == 0)
            && ((e.stateMask & SWT.SHIFT) == 0)) {
                EE2EMiniBufferView.this.doCompletentAction(oldString);
            } else if ((e.character == '\r') || (e.character == '\n')) {
                EE2EMiniBufferView.this.doReturnAction();
            }
        }
		private String oldString = "";
	};
	private void doCompletentAction(String oldString) {
		String miniBuffer = this.text.getText();
		miniBuffer = miniBuffer.substring(0, miniBuffer.length() - 1);
		if ((0 < miniBuffer.length()) && oldString.equals(miniBuffer)) {
			this.text.setText("");
			this.text.insert(miniBuffer);
			return;
		}
		oldString = miniBuffer;
		this.list.removeAll();
		java.util.Collection set;
		if (this.completention != null) {
			set = this.completention.allCompletions(miniBuffer);
			set = EE2EMiniBufferView.subCompletions(miniBuffer, set);
			if (set != null) {
				java.util.Iterator ite = set.iterator();
				while (ite.hasNext()) {
					String string = (String) ite.next();
					this.list.add(string);
				}
			}
		} else {
			set = null;
		}
		miniBuffer = EE2EMiniBufferView.tryCompletion(miniBuffer, set);
		this.text.setText("");
		this.text.insert(miniBuffer);
	}
	private void doReturnAction() {
		String miniBuffer = this.text.getText();
		if (this.completention == null) {
			return;
		}
		this.completention.returnAction(miniBuffer);
        if(this.completention != null) {
            String title = this.completention.getTitleText();
            if(title != null) {
                this.setTitle(title);
            }
            this.setTagLIst(
                this.completention.getTagList(),
                this.completention.getTagListSelect());
        }
		if (this.text != null) {
			this.text.setText("");
		}
		if (this.list != null) {
			this.list.removeAll();
		}
	}

	private SelectionListener selectionListener = new SelectionListener() {
		/**
		 * Sent when selection occurs in the control.
		 * <p>
		 * For example, on some platforms selection occurs in
		 * a List when the user selects an item or items.
		 * </p>
		 *
		 * @param e an event containing information about the selection
		 */
		public void widgetSelected(SelectionEvent e) {
			int index = EE2EMiniBufferView.this.list.getSelectionIndex();
			String string = EE2EMiniBufferView.this.list.getItem(index);
			if ((string == null) || (string.equals(""))) {
				return;
			}
			String ans = string;
			EE2EMiniBufferView.this.text.setText("");
			EE2EMiniBufferView.this.text.insert(ans);
			EE2EMiniBufferView.this.text.forceFocus();
		}

		/**
		 * Sent when default selection occurs in the control.
		 * <p>
		 * For example, on some platforms default selection occurs
		 * in a List when the user double-clicks an item or types
		 * return in a Text.
		 * </p>
		 *
		 * @param e an event containing information about the default selection
		 */
		public void widgetDefaultSelected(SelectionEvent e) {
		}
	};
	/** A result is returned from a complement list
	 * @param string The value of mini buffer.
	 * @param list Complement list.
	 * @return Complement result.
	 */
	protected static final String tryCompletion(
		String string,
		java.util.Collection set) {
		if ((set == null) || (set.size() <= 0)) {
			return string;
		}
		if (string == null) {
			string = "";
		}
		String topString = (String) (set.iterator().next());
		int i = -1;
		boolean flag = true;
		while (flag) {
			i++;
			java.util.Iterator ite = set.iterator();
			String top = (String) ite.next();
			if (top.length() <= i) {
				break;
			}
			if (i < string.length()) {
				if (getLower(string.charAt(i)) != getLower(top.charAt(i))) {
					return string;
				}
			}
			char old = getLower(top.charAt(i));
			while (ite.hasNext()) {
				String nextStr = (String) ite.next();
				char next = getLower(nextStr.charAt(i));
				if (next != old) {
					flag = false;
					break;
				}
			}
		}
		if (i < string.length()) {
			return string;
		}
		return topString.substring(0, i);
	}
	/** The list which matched from given list is returned.
	 * @param string match string.
	 * @param allList input list.
	 * @return output list.
	 */
	protected static final java.util.Collection subCompletions(
		String string,
		java.util.Collection allList) {
		if (allList == null) {
			return null;
		}
		if (string == null) {
			return allList;
		}
		if (string.length() <= 0) {
			return allList;
		}
		java.util.Set set = new java.util.TreeSet();
		char[] stringCh = string.toLowerCase().toCharArray();
		java.util.Iterator ite = allList.iterator();
		while (ite.hasNext()) {
			String next = (String) ite.next();
			if (next.length() < string.length()) {
				continue;
			}
			boolean flag = true;
			char[] listCh = next.toLowerCase().toCharArray();
			for (int j = 0; j < stringCh.length; j++) {
				if (stringCh[j] != listCh[j]) {
					flag = false;
					break;
				}
			}
			if (flag) {
				set.add(next);
			}
		}
		return set;
	}

	/**
	 * A capital letter is converted with a small letter.
	 */
	protected static final char getLower(char old) {
		if (('A' <= old) && (old <= 'Z')) {
			char next = (char) (old - 'A');
			return ((char) (next + 'a'));
		}
		if (old == '\\') {
			return '/';
		}
		return old;
	}
	/**
	*
	*/
	protected void dataClearAndDisable() {
		EE2EDisplayCompletion work = this.completention;
		this.completention = null;
		if (work != null) {
			work.dispose();
		}
		if((this.text != null) && (!this.text.isDisposed())) {
            this.text.setText("");
            this.text.setEnabled(false);
		}
		if((this.list != null) && (!this.list.isDisposed())) {
            this.list.removeAll();
            this.list.setEnabled(false);
		}
	}
    
    /**
     *
     */
    public void setTagLIst(java.util.Collection text,String selection) {
        if(text == null) {
            return;
        }
        java.util.Iterator ite = text.iterator();
        this.tagList.removeAll();
        int i = 0;
        this.tagList.setEnabled(false);
        int index = -1;
        while (ite.hasNext()) {
            String ans = (String) ite.next();
            if((selection != null) && (selection.equals(ans))) {
                index = i;
            }
            this.tagList.add(ans);
            i++;
        }
        if(0 <= index) {
            this.tagList.select(index);
        }
    }
	/**
	 * @see org.eclipse.ui.IWorkbenchPart#dispose()
	 */
	public void dispose() {
		super.dispose();
        this.dataClearAndDisable();
        if((this.text != null) && (!this.text.isDisposed())) {
            this.text.dispose();
		}
        this.text = null;
		if((this.list != null) && (!this.list.isDisposed())) {
            this.list.dispose();
		}
        this.list = null;
	}
	private EE2EDisplayCompletion completention;
	private Text text;
    private List list;
    private List tagList;
}
