package org.minimalj.frontend.form.element;

import java.util.Objects;

import org.minimalj.frontend.Frontend;
import org.minimalj.frontend.Frontend.IComponent;
import org.minimalj.frontend.Frontend.Input;
import org.minimalj.frontend.Frontend.InputComponentListener;
import org.minimalj.frontend.Frontend.InputType;
import org.minimalj.model.properties.PropertyInterface;
import org.minimalj.model.validation.InvalidValues;
import org.minimalj.model.validation.Validatable;
import org.minimalj.util.StringUtils;
import org.minimalj.util.mock.Mocking;

public abstract class FormatFormElement<T> extends AbstractFormElement<T> implements Enable, Mocking {

	private final boolean editable;
	
	/*
	 * textField is instantiated lazy because callbacks are used
	 * and the subclasses need a chance to initialize the values
	 */
	protected Input<String> textField;

	public FormatFormElement(PropertyInterface property, boolean editable) {
		super(property);
		this.editable = editable;
	}

	protected abstract String getAllowedCharacters(PropertyInterface property);

	protected abstract int getAllowedSize(PropertyInterface property);

	protected InputType getInputType() {
		return InputType.FREE;
	}

	@Override
	public IComponent getComponent() {
		if (textField == null) {
			if (editable) {
				textField = Frontend.getInstance().createTextField(getAllowedSize(getProperty()), getAllowedCharacters(getProperty()),
						getInputType(), null, new TextFormatFieldChangeListener());
			} else {
				textField = Frontend.getInstance().createReadOnlyTextField();
			}

		}
		return textField;
	}

	@Override
	public final T getValue() {
		return parse(textField.getValue());
	}

	protected abstract T parse(String text);
	
	@Override
	public final void setValue(T newValue) {
		T oldValue = parse(textField.getValue());
		if (!Objects.equals(oldValue, newValue)) {
			String oldString = render(oldValue);
			String newString = render(newValue);
			if (!StringUtils.equals(oldString, newString)) {
				textField.setValue(newString);
			}
		}
	}

	protected abstract String render(T value);
	
	private class TextFormatFieldChangeListener implements InputComponentListener {
		@Override
		public void changed(IComponent source) {
			// Formattierung auslösen
			T value = getValue();
			boolean valid = true;
			valid &= !InvalidValues.isInvalid(value);
			valid &= !(value instanceof Validatable) || ((Validatable) value).validate() == null;

			if (valid) {
				setValue(value);
			}
			
			fireChange();
		}
	}
	
	@Override
	public void setEnabled(boolean enabled) {
		textField.setEditable(enabled);
	}

}

@@ -42,35 +42,8 @@
 t;%0A%0A
-import java.util.Objects;%0A%0A
 impo
@@ -1732,150 +1732,17 @@
 e(T 
-newValue) %7B%0A%09%09T oldValue = parse(textField.getValue());%0A%09%09if (!Objects.equals(oldValue, newV
+v
 alue)
-)
  %7B%0A
-%09%09%09String oldString = render(oldValue);%0A%09
 %09%09St
@@ -1769,20 +1769,16 @@
 der(
-newV
+v
 alue);%0A
-%09
 %09%09if
@@ -1803,19 +1803,19 @@
 als(
-old
+new
 String, 
 newS
@@ -1814,23 +1814,33 @@
 ng, 
-newString
+textField.getValue()
 )) %7B%0A
-%09
 %09%09%09t
@@ -1869,21 +1869,16 @@
 tring);%0A
-%09%09%09%7D%0A
 %09%09%7D%0A%09%7D%0A%0A

revert last checkin