package org.minimalj.frontend.form.element;

import java.util.List;

import org.minimalj.frontend.action.Action;
import org.minimalj.frontend.editor.Editor;
import org.minimalj.frontend.form.Form;
import org.minimalj.model.properties.PropertyInterface;
import org.minimalj.util.CloneHelper;
import org.minimalj.util.GenericUtils;

public abstract class ListFormElement<T> extends AbstractObjectFormElement<List<T>> {
	// private static final Logger logger = Logger.getLogger(ObjectField.class.getName());
	
	public ListFormElement(PropertyInterface property) {
		this(property, true);
	}

	public ListFormElement(PropertyInterface property, boolean editable) {
		super(property, editable);
	}
	
	@Override
	protected void show(List<T> objects) {
		for (T entry : objects) {
			showEntry(entry);
		}
	}

	protected abstract void showEntry(T entry);
	
	protected abstract Form<T> createForm(boolean edit);
	
	private abstract class ListFormElementEditor extends Editor<T, Void> {
		public ListFormElementEditor() {
			assertEditable(this);
		}

		public ListFormElementEditor(String name) {
			super(name);
			assertEditable(this);
		}

		@Override
		protected Class<?> getEditedClass() {
			return GenericUtils.getGenericClass(ListFormElement.this.getClass());
		}
	}
	
	public class AddListEntryEditor extends ListFormElementEditor {
		
		public AddListEntryEditor() {
		}

		public AddListEntryEditor(String name) {
			super(name);
		}
		
		@Override
		protected T createObject() {
			@SuppressWarnings("unchecked")
			Class<T> clazz = (Class<T>) org.minimalj.util.GenericUtils.getGenericClass(ListFormElement.this.getClass());
			T newInstance = CloneHelper.newInstance(clazz);
			return newInstance;
		}
		
		@Override
		protected Form<T> createForm() {
			return ListFormElement.this.createForm(true);
		}
		
		@Override
		public Void save(T entry) {
			addEntry(entry);
			return null;
		}

		protected void addEntry(T entry) {
			getValue().add(entry);
		}

		@Override
		protected void finished(Void result) {
			handleChange();
		}
	}

	protected Action getEditorAction() {
		throw new RuntimeException(getClass().getSimpleName() + " must not use getEditorAction. Please use an extension of EditListEntryAction");
	}

	public class ListEntryEditor extends ListFormElementEditor {
		private final T originalEntry;
		
		public ListEntryEditor(T originalEntry) {
			this.originalEntry = originalEntry;
		}
		
		@Override
		protected T createObject() {
			return CloneHelper.clone(originalEntry);
		}
		
		@Override
		protected Form<T> createForm() {
			return ListFormElement.this.createForm(true);
		}

		@Override
		public Void save(T entry) {
			editEntry(originalEntry, entry);
			return null;
		}

		protected void editEntry(T originalEntry, T entry) {
			CloneHelper.deepCopy(entry, originalEntry);
		}

		@Override
		protected void finished(Void result) {
			handleChange();
		}
	}
	
	protected class RemoveEntryAction extends Action {
		private final T entry;
		
		public RemoveEntryAction(T entry) {
			this.entry = entry;
		}
		
		@Override
		public void action() {
			getValue().remove(entry);
			handleChange();
		}
    };

}

@@ -1268,438 +1268,514 @@
 %09%0A%09p
-ublic class AddListEntryEditor extends ListFormElementEditor %7B%0A%09%09%0A%09%09public AddListEntryEditor() %7B%0A%09%09%7D%0A%0A%09%09public AddListEntryEditor(String name) %7B%0A%09%09%09super(name);%0A%09%09%7D%0A%09%09%0A%09%09@Override%0A%09%09protected T createObject() %7B%0A%09%09%09@SuppressWarnings(%22unchecked%22)%0A%09%09%09Class%3CT%3E clazz = (Class%3CT%3E) org.minimalj.util.GenericUtils.getGenericClass(ListFormElement.this.getClass());%0A%09%09%09T newInstance = CloneHelper.newInstance(clazz);%0A%09%09%09return newInstance
+rotected T createEntry() %7B%0A%09%09@SuppressWarnings(%22unchecked%22)%0A%09%09Class%3CT%3E clazz = (Class%3CT%3E) org.minimalj.util.GenericUtils.getGenericClass(ListFormElement.this.getClass());%0A%09%09T newInstance = CloneHelper.newInstance(clazz);%0A%09%09return newInstance;%0A%09%7D%0A%09%0A%09public class AddListEntryEditor extends ListFormElementEditor %7B%0A%09%09%0A%09%09public AddListEntryEditor() %7B%0A%09%09%7D%0A%0A%09%09public AddListEntryEditor(String name) %7B%0A%09%09%09super(name);%0A%09%09%7D%0A%09%09%0A%09%09@Override%0A%09%09protected T createObject() %7B%0A%09%09%09return ListFormElement.this.createEntry()
 ;%0A%09%09

make createEntry changeable