package inline;

import wicket.ajax.AjaxRequestTarget;
import wicket.ajax.IAjaxCallDecorator;
import wicket.ajax.calldecorator.AjaxCallDecorator;
import wicket.ajax.form.AjaxFormComponentUpdatingBehavior;
import wicket.ajax.form.AjaxFormSubmitBehavior;
import wicket.ajax.markup.html.AjaxFallbackLink;
import wicket.extensions.ajax.markup.html.repeater.data.table.AjaxFallbackDefaultDataTable;
import wicket.extensions.markup.html.repeater.data.table.PropertyColumn;
import wicket.markup.html.WebPage;
import wicket.markup.html.basic.Label;
import wicket.markup.html.form.CheckBox;
import wicket.markup.html.form.Form;
import wicket.markup.html.link.InternalFrame;
import wicket.model.Model;
import wicket.model.PropertyModel;

import java.util.ArrayList;
import java.util.List;

/**
 * This page demonstrates an issue I am running into when trying to use an iframe when
 * Ajax calls are made within the iframe or outside of it.  There are two scenarios here,
 * Scenario 1:
 * 1) Click the submit button
 * 2) Click either the checkbox or the link
 * 3) Now sort or page the data table, a page expired error comes up.  The following logging displays
 * indicating that the version can't be found:
 * [wicket.Page] No version manager available to retrieve requested versionNumber 1
 * [wicket.PageMap] Unable to get version 1 of page [Page class = inline.InlinePage, id = 1]
 *
 * Scenario 2:
 * 1) Click the submit button
 * 2) Sort or page the data table.
 * 3) Click on the link or check box, an internal error with the stacktrace of the following
 * occurs:
 * <pre>
 * 2006-10-24 15:15:04,941 ERROR [wicket.RequestCycle] Cannot remove [MarkupContainer [Component id = 2, page = &lt;No Page&gt;, path = 2.Loop$LoopItem]] from null parent!
 * java.lang.IllegalStateException: Cannot remove [MarkupContainer [Component id = 2, page = &lt;No Page&gt;, path = 2.Loop$LoopItem]] from null parent!
 * 	at wicket.Component.remove(Component.java:1475)
 * 	at wicket.version.undo.Add.undo(Add.java:81)
 * 	at wicket.version.undo.ChangeList.undo(ChangeList.java:93)
 * 	at wicket.version.undo.UndoPageVersionManager.undo(UndoPageVersionManager.java:217)
 * 	at wicket.version.undo.UndoPageVersionManager.getVersion(UndoPageVersionManager.java:167)
 * 	at wicket.Page.getVersion(Page.java:586)
 * 	at wicket.PageMap.access(PageMap.java:658)
 * 	at wicket.PageMap.get(PageMap.java:466)
 * 	at wicket.Session.getPage(Session.java:418)
 * 	at wicket.request.compound.DefaultRequestTargetResolverStrategy.resolveRenderedPage(DefaultRequestTargetResolverStrategy.java:215)
 * 	at wicket.request.compound.DefaultRequestTargetResolverStrategy.resolve(DefaultRequestTargetResolverStrategy.java:152)
 * 	at wicket.request.compound.AbstractCompoundRequestCycleProcessor.resolve(AbstractCompoundRequestCycleProcessor.java:48)
 * 	at wicket.RequestCycle.step(RequestCycle.java:948)
 * 	at wicket.RequestCycle.steps(RequestCycle.java:1040)
 * 	at wicket.RequestCycle.request(RequestCycle.java:454)
 * 	at wicket.protocol.http.WicketServlet.doGet(WicketServlet.java:216)
 * </pre>
 */
public class HomePage extends WebPage {
    private int count = 0;
    private int clickCount;
    private int submitCount;
    private InternalFrame inlineFrame;

    public HomePage() {
        //simple test form simulates a query
        Form f = new Form("testForm");
        add(f);

        final Label label3;
        f.add(label3 = new Label("label3",new PropertyModel(this,"submitCount")));
        label3.setOutputMarkupId(true);
        f.add(new AjaxFormSubmitBehavior(f, "onsubmit") {
            protected IAjaxCallDecorator getAjaxCallDecorator() {
                return new AjaxCallDecorator() {
                    public CharSequence decorateScript(CharSequence script) {
                        return script + "return false;";
                    }
                };
            }

            protected void onSubmit(AjaxRequestTarget target) {
                submitCount++;
                target.addComponent(label3);
                target.addComponent(inlineFrame);
            }
        });

        //data table population would be the result of the query
        List<PropertyColumn> columns = new ArrayList<PropertyColumn>();
        columns.add(
                new PropertyColumn(new Model("First Name"), "firstName", "firstName"));
        columns.add(new PropertyColumn(new Model("Last Name"), "lastName", "lastName"));
        AjaxFallbackDefaultDataTable dataTable = new AjaxFallbackDefaultDataTable(
                InlinePage.TABLE_ID, columns,
                createProvider(), 5);
        add(dataTable);

        //inline viewer
        InlinePage viewer = new InlinePage(dataTable);
        add(inlineFrame = new InternalFrame("people", viewer.getPageMap(), viewer));
        inlineFrame.setOutputMarkupId(true);

        //tracks the number of times the link was clicked
        final Label label =
                new Label("label", new PropertyModel(this, "count", int.class));
        label.setOutputMarkupId(true);
        final AjaxFallbackLink link = new AjaxFallbackLink("link") {
            public void onClick(final AjaxRequestTarget target) {
                count++;
                if (target != null) {
                    target.addComponent(label);
                }
            }
        };
        add(link);
        add(label);

        //tracks the number of times the checkbox was clicked
        final Label label2 = new Label("label2", new PropertyModel(this,"clickCount"));
        label2.setOutputMarkupId(true);

        CheckBox checkbox = new CheckBox("checkbox", new Model(Boolean.FALSE));
        checkbox.add(new AjaxFormComponentUpdatingBehavior("onclick") {
            protected void onUpdate(AjaxRequestTarget target) {
                clickCount++;
                target.addComponent(label2);
            }
        });

        add(checkbox);
        add(label2);
    }

    //getters for PropertyModels
    public int getCount() {
        return count;
    }

    public int getSubmitCount() {
        return submitCount;
    }

    public int getClickCount() {
        return clickCount;
    }

    //private builder method for the data
    private static PersonDataProvider createProvider() {
        List<Person> people = new ArrayList<Person>();
        int guid = 0;
        people.add(new Person(++guid, "Homer", "Simpson"));
        people.add(new Person(++guid, "Marge", "Simpson"));
        people.add(new Person(++guid, "Maggie", "Simpson"));
        people.add(new Person(++guid, "Lisa", "Simpson"));
        people.add(new Person(++guid, "Bart", "Simpson"));
        people.add(new Person(++guid, "Ralph", "Wiggum"));
        people.add(new Person(++guid, "Clancy", "Wiggum"));
        people.add(new Person(++guid, "Montegomery", "Burns"));
        people.add(new Person(++guid, "Peter", "Griffen"));
        people.add(new Person(++guid, "Meg", "Griffen"));
        people.add(new Person(++guid, "Stewie", "Griffen"));
        people.add(new Person(++guid, "Luke", "Skywalker"));
        people.add(new Person(++guid, "Princess", "Leia"));
        return new PersonDataProvider(people);
    }
}
