/*******************************************************************************
 * Copyright (c) 2006, 2015 The Pampered Chef and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     The Pampered Chef - initial API and implementation
 ******************************************************************************/

package org.eclipse.jface.examples.databinding.mask;

import java.beans.PropertyChangeListener;
import java.beans.PropertyChangeSupport;

import org.eclipse.jface.examples.databinding.mask.internal.EditMaskParser;
import org.eclipse.jface.examples.databinding.mask.internal.SWTUtil;
import org.eclipse.swt.events.DisposeEvent;
import org.eclipse.swt.events.DisposeListener;
import org.eclipse.swt.events.FocusAdapter;
import org.eclipse.swt.events.FocusEvent;
import org.eclipse.swt.events.FocusListener;
import org.eclipse.swt.events.VerifyEvent;
import org.eclipse.swt.events.VerifyListener;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Text;

/**
 * Ensures text widget has the format specified by the edit mask.  Edit masks
 * are currently defined as follows:
 *
 * The following characters are reserved words that match specific kinds of
 * characters:
 *
 * # - digits 0-9
 * A - uppercase A-Z
 * a - upper or lowercase a-z, A-Z
 * n - alphanumeric 0-9, a-z, A-Z
 *
 * All other characters are literals.  The above characters may be turned into
 * literals by preceeding them with a backslash.  Use two backslashes to
 * denote a backslash.
 *
 * Examples:
 *
 * (###) ###-####  U.S. phone number
 * ###-##-####     U.S. Social Security number
 * \\\###          A literal backslash followed by a literal pound symbol followed by two digits
 *
 * Ideas for future expansion:
 *
 * Quantifiers as postfix modifiers to a token.  ie:
 *
 * #{1, 2}/#{1,2}/####   MM/DD/YYYY date format allowing 1 or 2 digit month or day
 *
 * Literals may only be quantified as {0,1} which means that they only appear
 * if placeholders on both sides of the literal have data.  This will be used
 * along with:
 *
 * Right-to-left support for numeric entry.  When digits are being entered and
 * a decimal point is present in the mask, digits to the left of the decimal
 * are entered right-to-left but digits to the right of the decimal left-to-right.
 * This might need to be a separate type of edit mask. (NumericMask, maybe?)
 *
 * Example:
 *
 * $#{0,3},{0,1}#{0,3}.#{0,2}  ie: $123,456.12 or $12.12 or $1,234.12 or $123.12
 *
 *
 * Here's the basic idea of how the current implementation works (the actual
 * implementation is slightly more abstracted and complicated than this):
 *
 * We always let the verify event pass if the user typed a new character or selected/deleted anything.
 * During the verify event, we post an async runnable.
 * Inside that async runnable, we:
 *   - Remember the selection position
 *   - getText(), then
 *   - Strip out all literal characters from text
 *   - Truncate the resulting string to raw length of edit mask without literals
 *   - Insert literal characters back in the correct positions
 *   - setText() the resulting string
 *   - reset the selection to the correct location
 *
 * @since 3.3
 */
public class EditMask {

	public static final String FIELD_TEXT = "text";
	public static final String FIELD_RAW_TEXT = "rawText";
	public static final String FIELD_COMPLETE = "complete";
	protected Text text;
	protected EditMaskParser editMaskParser;
	private boolean fireChangeOnKeystroke = true;
	private PropertyChangeSupport propertyChangeSupport = new PropertyChangeSupport(this);

	protected String oldValidRawText = "";
	protected String oldValidText = "";

	/**
	 * Creates an instance that wraps around a text widget and manages its<br>
	 * formatting.
	 *
	 * @param text
	 * @param editMask
	 */
	public EditMask(Text text) {
		this.text = text;
	}

	/**
	 * @return the underlying Text control used by EditMask
	 */
	public Text getControl() {
		return this.text;
	}

	/**
	 * Set the edit mask string on the edit mask control.
	 *
	 * @param editMask The edit mask string
	 */
	public void setMask(String editMask) {
		editMaskParser = new EditMaskParser(editMask);
		text.addVerifyListener(verifyListener);
		text.addFocusListener(focusListener);
		text.addDisposeListener(disposeListener);
		updateTextField.run();
		oldValidText = text.getText();
		oldValidRawText = editMaskParser.getRawResult();
	}

    /**
     * @param string Sets the text string in the receiver
     */
    public void setText(String string) {
    	String oldValue = text.getText();
    	if (editMaskParser != null) {
			editMaskParser.setInput(string);
			String formattedResult = editMaskParser.getFormattedResult();
			text.setText(formattedResult);
			firePropertyChange(FIELD_TEXT, oldValue, formattedResult);
    	} else {
    		text.setText(string);
			firePropertyChange(FIELD_TEXT, oldValue, string);
    	}
		oldValidText = text.getText();
		oldValidRawText = editMaskParser.getRawResult();
	}

	/**
	 * @return the actual (formatted) text
	 */
	public String getText() {
		if (editMaskParser != null) {
			return editMaskParser.getFormattedResult();
		}
		return text.getText();
	}

	/**
	 * setRawText takes raw text as a parameter but formats it before
	 * setting the text in the Text control.
	 *
	 * @param string the raw (unformatted) text
	 */
	public void setRawText(String string)  {
		if (string == null) {
			string = "";
		}
		if (editMaskParser != null) {
			String oldValue = editMaskParser.getRawResult();
			editMaskParser.setInput(string);
			text.setText(editMaskParser.getFormattedResult());
			firePropertyChange(FIELD_RAW_TEXT, oldValue, string);
		} else {
	    	String oldValue = text.getText();
    		text.setText(string);
			firePropertyChange(FIELD_RAW_TEXT, oldValue, string);
		}
		oldValidText = text.getText();
		oldValidRawText = editMaskParser.getRawResult();
	}

	/**
	 * @return The input text with literals removed
	 */
	public String getRawText() {
		if (editMaskParser != null) {
			return editMaskParser.getRawResult();
		}
		return text.getText();
	}

	/**
	 * @return true if the field is complete according to the mask; false otherwise
	 */
	public boolean isComplete() {
		if (editMaskParser == null) {
			return true;
		}
		return editMaskParser.isComplete();
	}

	/**
	 * Returns the placeholder character.  The placeholder
	 * character must be a different character than any character that is
	 * allowed as input anywhere in the edit mask.  For example, if the edit
	 * mask permits spaces to be used as input anywhere, the placeholder
	 * character must be something other than a space character.
	 * <p>
	 * The space character is the default placeholder character.
	 *
	 * @return the placeholder character
	 */
	public char getPlaceholder() {
		if (editMaskParser == null) {
			throw new IllegalArgumentException("Have to set an edit mask first");
		}
		return editMaskParser.getPlaceholder();
	}

	/**
	 * Sets the placeholder character for the edit mask.  The placeholder
	 * character must be a different character than any character that is
	 * allowed as input anywhere in the edit mask.  For example, if the edit
	 * mask permits spaces to be used as input anywhere, the placeholder
	 * character must be something other than a space character.
	 * <p>
	 * The space character is the default placeholder character.
	 *
	 * @param placeholder The character to use as a placeholder
	 */
	public void setPlaceholder(char placeholder) {
		if (editMaskParser == null) {
			throw new IllegalArgumentException("Have to set an edit mask first");
		}
		editMaskParser.setPlaceholder(placeholder);
		updateTextField.run();
		oldValidText = text.getText();
	}

	/**
	 * Indicates if change notifications will be fired after every keystroke
	 * that affects the value of the rawText or only when the value is either
	 * complete or empty.
	 *
	 * @return true if every change (including changes from one invalid state to
	 *         another) triggers a change event; false if only empty or valid
	 *         values trigger a change event.  Defaults to false.
	 */
	public boolean isFireChangeOnKeystroke() {
		return fireChangeOnKeystroke;
	}

	/**
	 * Sets if change notifications will be fired after every keystroke that
	 * affects the value of the rawText or only when the value is either
	 * complete or empty.
	 *
	 * @param fireChangeOnKeystroke
	 *            true if every change (including changes from one invalid state
	 *            to another) triggers a change event; false if only empty or
	 *            valid values trigger a change event.  Defaults to false.
	 */
	public void setFireChangeOnKeystroke(boolean fireChangeOnKeystroke) {
		this.fireChangeOnKeystroke = fireChangeOnKeystroke;
	}

	/**
	 * JavaBeans boilerplate code...
	 *
	 * @param listener
	 */
	public void addPropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(listener);
	}

	/**
	 * JavaBeans boilerplate code...
	 *
	 * @param propertyName
	 * @param listener
	 */
	public void addPropertyChangeListener(String propertyName,
			PropertyChangeListener listener) {
		propertyChangeSupport.addPropertyChangeListener(propertyName, listener);
	}

	/**
	 * JavaBeans boilerplate code...
	 *
	 * @param listener
	 */
	public void removePropertyChangeListener(PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(listener);
	}

	/**
	 * JavaBeans boilerplate code...
	 *
	 * @param propertyName
	 * @param listener
	 */
	public void removePropertyChangeListener(String propertyName,
			PropertyChangeListener listener) {
		propertyChangeSupport.removePropertyChangeListener(propertyName,
				listener);
	}

	private boolean isEitherValueNotNull(Object oldValue, Object newValue) {
		return oldValue != null || newValue != null;
	}

	private void firePropertyChange(String propertyName, Object oldValue,
			Object newValue) {
		if (isEitherValueNotNull(oldValue, newValue)) {
			propertyChangeSupport.firePropertyChange(propertyName,
					oldValue, newValue);
		}
	}

	protected boolean updating = false;

	protected int oldSelection = 0;
	protected int selection = 0;
	protected String oldRawText = "";
   protected boolean replacedSelectedText = false;

	private VerifyListener verifyListener = new VerifyListener() {
		@Override
		public void verifyText(VerifyEvent e) {
         // If the edit mask is already full, don't let the user type
         // any new characters
         if (editMaskParser.isComplete() && // should eventually be .isFull() to account for optional characters
               e.start == e.end &&
               e.text.length() > 0)
         {
            e.doit=false;
            return;
         }

			oldSelection = selection;
			Point selectionRange = text.getSelection();
         selection = selectionRange.x;

			if (!updating) {
   			replacedSelectedText = false;
   			if (selectionRange.y - selectionRange.x > 0 && e.text.length() > 0) {
   			   replacedSelectedText = true;
   			}
            // If the machine is loaded down (ie: spyware, malware), we might
            // get another keystroke before asyncExec can process, so we use
            // greedyExec instead.
            SWTUtil.greedyExec(Display.getCurrent(), updateTextField);
//				Display.getCurrent().asyncExec(updateTextField);
         }
		}
	};

	private Runnable updateTextField = new Runnable() {
		@Override
		public void run() {
			updating = true;
			try {
				if (!text.isDisposed()) {
					Boolean oldIsComplete = Boolean.valueOf(editMaskParser.isComplete());

					editMaskParser.setInput(text.getText());
					text.setText(editMaskParser.getFormattedResult());
					String newRawText = editMaskParser.getRawResult();

					updateSelectionPosition(newRawText);
					firePropertyChangeEvents(oldIsComplete, newRawText);
				}
			} finally {
				updating = false;
			}
		}

		private void updateSelectionPosition(String newRawText) {

         // Adjust the selection
         if (isInsertingNewCharacter(newRawText) || replacedSelectedText) {
            // Find the position after where the new character was actually inserted
            int selectionDelta =
               editMaskParser.getNextInputPosition(oldSelection)
               - oldSelection;
            if (selectionDelta == 0) {
               selectionDelta = editMaskParser.getNextInputPosition(selection)
               - selection;
            }
            selection += selectionDelta;
         }

			// Did we just type something that was accepted by the mask?
			if (!newRawText.equals(oldRawText)) { // yep

            // If the user hits <end>, bounce them back to the end of their actual input
				int firstIncompletePosition = editMaskParser.getFirstIncompleteInputPosition();
				if (firstIncompletePosition > 0 && selection > firstIncompletePosition)
					selection = firstIncompletePosition;
				text.setSelection(new Point(selection, selection));

			} else { // nothing was accepted by the mask

				// Either we backspaced over a literal or we typed an illegal character
				if (selection > oldSelection) { // typed an illegal character; backup
					text.setSelection(new Point(selection-1, selection-1));
				} else { // backspaced over a literal; don't interfere with selection position
					text.setSelection(new Point(selection, selection));
				}
			}
			oldRawText = newRawText;
		}

		private boolean isInsertingNewCharacter(String newRawText) {
			return newRawText.length() > oldRawText.length();
		}

		private void firePropertyChangeEvents(Boolean oldIsComplete, String newRawText) {
			Boolean newIsComplete = Boolean.valueOf(editMaskParser.isComplete());
			if (!oldIsComplete.equals(newIsComplete)) {
				firePropertyChange(FIELD_COMPLETE, oldIsComplete, newIsComplete);
			}
			if (!newRawText.equals(oldValidRawText)) {
				if ( newIsComplete.booleanValue() || "".equals(newRawText) || fireChangeOnKeystroke) {
					firePropertyChange(FIELD_RAW_TEXT, oldValidRawText, newRawText);
					firePropertyChange(FIELD_TEXT, oldValidText, text.getText());
					oldValidText = text.getText();
					oldValidRawText = newRawText;
				}
			}
		}
	};

	private FocusListener focusListener = new FocusAdapter() {
		@Override
		public void focusGained(FocusEvent e) {
			selection = editMaskParser.getFirstIncompleteInputPosition();
			text.setSelection(selection, selection);
		}
	};

	private DisposeListener disposeListener = new DisposeListener() {
		@Override
		public void widgetDisposed(DisposeEvent e) {
			text.removeVerifyListener(verifyListener);
			text.removeFocusListener(focusListener);
			text.removeDisposeListener(disposeListener);
		}
	};

}
