package ca.krasnay.panelized;

import java.util.List;

import org.apache.wicket.markup.ComponentTag;
import org.apache.wicket.markup.html.form.DropDownChoice;
import org.apache.wicket.markup.html.form.IChoiceRenderer;
import org.apache.wicket.model.IModel;
import org.apache.wicket.model.Model;

/**
 * Control that encapsulates a DropDownChoice component.
 *
 * @author John Krasnay <john@krasnay.ca>
 */
public class DropDownControl<T> extends AbstractControl<T> {

    private DropDownChoice<T> dropDownChoice;

    private boolean required;

    private IModel<String> nullOptionText;

    public DropDownControl(String id) {
        this(id, (List<T>) null);
    }

    public DropDownControl(String id, IModel<List<? extends T>> choices) {
        this(id, null, choices);
    }

    public DropDownControl(String id, IModel<T> model, IModel<List<? extends T>> choices) {

        super(id, model);

        dropDownChoice = new DropDownChoice<T>("component", new DelegateModel<T>(this), choices) {

            @Override
            protected CharSequence getDefaultChoice(final String selected) {

                if (nullOptionText == null) {

                    return super.getDefaultChoice(selected);

                } else {

                    boolean noSelection = selected == null || selected.equals("");

                    if (isNullValid() || noSelection) {

                        StringBuilder sb = new StringBuilder();

                        sb.append("\n<option");

                        if (noSelection) {
                            sb.append(" selected=\"selected\"");
                        }

                        sb.append(" value=\"\">").append(nullOptionText.getObject()).append("</option>");
                        return sb;

                    } else {

                        return "";

                    }
                }
            }

            @Override
            public boolean isEnabled() {
                return isEnabledInternal();
            };

            @Override
            public boolean isRequired() {
                return DropDownControl.this.isRequired();
            }

            @Override
            protected void onComponentTag(ComponentTag tag) {
                super.onComponentTag(tag);
                onDropDownComponentTag(tag);
            }
        };

        add(dropDownChoice);

    }

    public DropDownControl(String id, IModel<T> model, List<T> choices) {
        this(id, model, Model.ofList(choices));
    }

    public DropDownControl(String id, List<T> choices) {
        this(id, null, Model.ofList(choices));
    }

    public DropDownChoice<T> getFormComponent() {
        return dropDownChoice;
    }

    public DropDownChoice<T> getDropDownChoice() {
        return dropDownChoice;
    }

    @Override
    public boolean isRequired() {
        return required;
    }

//    public DropDownControl<T> onChange(final AjaxAction action) {
//        getFormComponent().add(new AjaxFormComponentUpdatingBehavior("onchange") {
//            @Override
//            protected void onUpdate(AjaxRequestTarget target) {
//                action.invoke(target);
//            }
//        });
//        return this;
//    }

    /**
     * Callback method called from the onComponentTag field of the DropDownControl.
     * Here we can do last-minute changes to the tag.
     *
     * <p>This is called at the end of onComponentTag after the parent
     * implementations have been invoked, so this method can override those
     * tag changes.
     *
     * <p>The default implementation does nothing.
     */
    protected void onDropDownComponentTag(ComponentTag tag) {

    }

    public DropDownControl<T> setChoiceRenderer(IChoiceRenderer<T> renderer) {
        getDropDownChoice().setChoiceRenderer(renderer);
        return this;
    }

    public DropDownControl<T> setChoices(IModel<? extends List<? extends T>> choices) {
        getDropDownChoice().setChoices(choices);
        return this;
    }

    public DropDownControl<T> setChoices(List<? extends T> choices) {
        return setChoices(Model.ofList(choices));
    }

    public DropDownControl<T> setNullOptionText(IModel<String> nullOptionText) {
        this.nullOptionText = nullOptionText;
        return this;
    }

    public DropDownControl<T> setNullValid(boolean nullValid) {
        getDropDownChoice().setNullValid(nullValid);
        return this;
    }

    @Override
    public DropDownControl<T> setRequired(boolean required) {
        this.required = required;
        return this;
    }

}

@@ -48,16 +48,135 @@
 .List;%0A%0A
+import org.apache.wicket.ajax.AjaxRequestTarget;%0Aimport org.apache.wicket.ajax.form.AjaxFormComponentUpdatingBehavior;%0A
 import o
@@ -3340,24 +3340,763 @@
 s;%0A//    %7D%0A%0A
+    /**%0A     * Calls the provided action when the dropdown changes. Note that the model%0A     * object is updated when changed, as per Wicket's%0A     * AjaxFormComponentUpdatingBehavior. This means that action code can find%0A     * out the new value for this dropdown by inspecting the model object;%0A     * however, it means that even if the form is cancelled the model object%0A     * will have the new value.%0A     */%0A    public DropDownControl%3CT%3E onChange(final AjaxAction action) %7B%0A        dropDownChoice.add(new AjaxFormComponentUpdatingBehavior(%22onchange%22) %7B%0A            @Override%0A            protected void onUpdate(AjaxRequestTarget target) %7B%0A                action.invoke(target);%0A            %7D%0A        %7D);%0A        return this;%0A    %7D%0A%0A%0A
     /**%0A    

Implement DropDownControl.onChange