// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package org.apache.tapestry5.corelib.components;

import org.apache.tapestry5.*;
import org.apache.tapestry5.annotations.*;
import org.apache.tapestry5.corelib.internal.AjaxFormLoopContext;
import org.apache.tapestry5.dom.Element;
import org.apache.tapestry5.internal.services.RequestConstants;
import org.apache.tapestry5.ioc.annotations.Inject;
import org.apache.tapestry5.ioc.services.TypeCoercer;
import org.apache.tapestry5.json.JSONObject;
import org.apache.tapestry5.services.*;
import org.apache.tapestry5.services.ajax.AjaxResponseRenderer;
import org.apache.tapestry5.services.compatibility.DeprecationWarning;
import org.apache.tapestry5.services.javascript.JavaScriptSupport;

import java.util.Collections;
import java.util.Iterator;

/**
 * A special form of the {@link org.apache.tapestry5.corelib.components.Loop}
 * component that adds Ajax support to handle adding new rows and removing
 * existing rows dynamically.
 *
 * This component expects that the values being iterated over are entities that
 * can be identified via a {@link org.apache.tapestry5.ValueEncoder}, therefore
 * you must either bind the "encoder" parameter to a ValueEncoder or use an
 * entity type for the "value" parameter for which Tapestry can provide a
 * ValueEncoder automatically.
 *
 * Works with {@link org.apache.tapestry5.corelib.components.AddRowLink} and
 * {@link org.apache.tapestry5.corelib.components.RemoveRowLink} components.
 *
 * The addRow event will receive the context specified by the context parameter.
 *
 * The removeRow event will receive the client-side value for the row being iterated.
 *
 * @tapestrydoc
 * @see EventConstants#ADD_ROW
 * @see EventConstants#REMOVE_ROW
 * @see AddRowLink
 * @see RemoveRowLink
 * @see Loop
 */
@Events(
        {EventConstants.ADD_ROW, EventConstants.REMOVE_ROW})
@Import(module = "t5/core/ajaxformloop")
@SupportsInformalParameters
public class AjaxFormLoop
{
    /**
     * The element to render for each iteration of the loop. The default comes from the template, or "div" if the
     * template did not specify an element.
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    @Property(write = false)
    private String element;

    /**
     * The objects to iterate over (passed to the internal Loop component).
     */
    @Parameter(required = true, autoconnect = true)
    private Iterable source;

    /**
     * The current value from the source.
     */
    @Parameter(required = true)
    private Object value;

    /**
     * Name of a function on the client-side Tapestry.ElementEffect object that is invoked to make added content
     * visible. This was used by the FormInjector component (remove in 5.4), when adding a new row to the loop. Leaving as
     * null uses the default function, "highlight".
     *
     * @deprecated Deprecated in 5.4 with no replacement.
     */
    @Parameter(defaultPrefix = BindingConstants.LITERAL)
    private String show;

    /**
     * The context for the form loop (optional parameter). This list of values will be converted into strings and
     * included in the URI. The strings will be coerced back to whatever their values are and made available to event
     * handler methods. Note that the context is only encoded and available to the {@linkplain EventConstants#ADD_ROW addRow}
     * event; for the {@linkplain EventConstants#REMOVE_ROW} event, the context passed to event handlers
     * is simply the decoded value for the row that is to be removed.
     */
    @Parameter
    private Object[] context;

    /**
     * A block to render after the loo
     * This typically contains a {@link org.apache.tapestry5.corelib.components.AddRowLink}.
     */
    @Parameter(value = "block:defaultAddRow", defaultPrefix = BindingConstants.LITERAL)
    @Property(write = false)
    private Block addRow;

    /**
     * The block that contains the form injector (it is rendered last, as the "tail" of the AjaxFormLoop). This, in
     * turn, references the addRow block (from a parameter, or a default).
     */
    @Inject
    private Block tail;

    /**
     * A ValueEncoder used to convert server-side objects (provided by the
     * "source" parameter) into unique client-side strings (typically IDs) and
     * back. Note: this parameter may be OMITTED if Tapestry is configured to
     * provide a ValueEncoder automatically for the type of property bound to
     * the "value" parameter.
     */
    @Parameter(required = true, allowNull = false)
    private ValueEncoder<Object> encoder;

    @InjectComponent
    private FormFragment fragment;

    @Inject
    private Block ajaxResponse;

    @Inject
    private ComponentResources resources;

    @Environmental
    private FormSupport formSupport;

    @Environmental
    private Heartbeat heartbeat;

    @Inject
    private Environment environment;

    @Inject
    private JavaScriptSupport jsSupport;

    private Iterator iterator;

    private Element wrapper;

    @Inject
    private TypeCoercer typeCoercer;

    @Inject
    private ComponentDefaultProvider defaultProvider;

    @Inject
    private AjaxResponseRenderer ajaxResponseRenderer;

    @Inject
    private DeprecationWarning deprecationWarning;

    void pageLoaded()
    {
        deprecationWarning.ignoredComponentParameters(resources, "show");
    }

    ValueEncoder defaultEncoder()
    {
        return defaultProvider.defaultValueEncoder("value", resources);
    }

    private final AjaxFormLoopContext formLoopContext = new AjaxFormLoopContext()
    {
        public String encodedRowValue()
        {
            return encoder.toClient(value);
        }
    };

    String defaultElement()
    {
        return resources.getElementName("div");
    }

    /**
     * Action for synchronizing the current element of the loop by recording its client value.
     */
    static class SyncValue implements ComponentAction<AjaxFormLoop>
    {
        private final String clientValue;

        public SyncValue(String clientValue)
        {
            this.clientValue = clientValue;
        }

        public void execute(AjaxFormLoop component)
        {
            component.syncValue(clientValue);
        }

        @Override
        public String toString()
        {
            return String.format("AjaxFormLoop.SyncValue[%s]", clientValue);
        }
    }

    private static final ComponentAction<AjaxFormLoop> BEGIN_HEARTBEAT = new ComponentAction<AjaxFormLoop>()
    {
        public void execute(AjaxFormLoop component)
        {
            component.beginHeartbeat();
        }

        @Override
        public String toString()
        {
            return "AjaxFormLoop.BeginHeartbeat";
        }
    };

    @Property(write = false)
    private final Renderable beginHeartbeat = new Renderable()
    {
        public void render(MarkupWriter writer)
        {
            formSupport.storeAndExecute(AjaxFormLoop.this, BEGIN_HEARTBEAT);
        }
    };

    private static final ComponentAction<AjaxFormLoop> END_HEARTBEAT = new ComponentAction<AjaxFormLoop>()
    {
        public void execute(AjaxFormLoop component)
        {
            component.endHeartbeat();
        }

        @Override
        public String toString()
        {
            return "AjaxFormLoop.EndHeartbeat";
        }
    };

    @Property(write = false)
    private final Renderable endHeartbeat = new Renderable()
    {
        public void render(MarkupWriter writer)
        {
            formSupport.storeAndExecute(AjaxFormLoop.this, END_HEARTBEAT);
        }
    };

    @Property(write = false)
    private final Renderable beforeBody = new Renderable()
    {
        public void render(MarkupWriter writer)
        {
            beginHeartbeat();
            syncCurrentValue();
        }
    };

    @Property(write = false)
    private final Renderable afterBody = new Renderable()
    {
        public void render(MarkupWriter writer)
        {
            endHeartbeat();
        }
    };

    @SuppressWarnings(
            {"unchecked"})
    private void syncValue(String clientValue)
    {
        Object value = encoder.toValue(clientValue);

        if (value == null)
            throw new RuntimeException(String.format(
                    "Unable to convert client value '%s' back into a server-side object.", clientValue));

        this.value = value;
    }

    @Property(write = false)
    private final Renderable syncValue = new Renderable()
    {
        public void render(MarkupWriter writer)
        {
            syncCurrentValue();
        }
    };

    private void syncCurrentValue()
    {
        String id = toClientValue();

        // Add the command that restores value from the value clientValue,
        // when the form is submitted.

        formSupport.store(this, new SyncValue(id));
    }

    /**
     * Uses the {@link org.apache.tapestry5.ValueEncoder} to convert the current server-side value to a client-side
     * value.
     */
    @SuppressWarnings(
            {"unchecked"})
    private String toClientValue()
    {
        return encoder.toClient(value);
    }

    void setupRender(MarkupWriter writer)
    {
        pushContext();

        iterator = source == null ? Collections.EMPTY_LIST.iterator() : source.iterator();

        Link removeRowLink = resources.createEventLink("triggerRemoveRow", context);
        Link injectRowLink = resources.createEventLink("injectRow", context);

        injectRowLink.addParameter(RequestConstants.FORM_CLIENTID_PARAMETER, formSupport.getClientId());
        injectRowLink.addParameter(RequestConstants.FORM_COMPONENTID_PARAMETER, formSupport.getFormComponentId());

        // Fix for TAP5-227 - AjaxFormLoop dont work well inside a table tag
        Element element = writer.getElement();
        this.wrapper = element.getAttribute("data-container-type") != null
                || element.getAttribute("data-remove-row-url") != null
                || element.getAttribute("data-inject-row-url") != null ? writer.element("div") : null;

        writer.attributes("data-container-type", "core/AjaxFormLoop",
                "data-remove-row-url", removeRowLink,
                "data-inject-row-url", injectRowLink);
    }

    private void pushContext()
    {
        environment.push(AjaxFormLoopContext.class, formLoopContext);
    }

    boolean beginRender(MarkupWriter writer)
    {
        if (!iterator.hasNext())
        {
            return false;
        }

        value = iterator.next();

        // Return true: render the body for this value; that ends up being a form-fragment.

        return true;
    }

    Object afterRender(MarkupWriter writer)
    {
        // When out of source items to render, switch over to the addRow block (either the default,
        // or from the addRow parameter) before proceeding to cleanup render.

        if (!iterator.hasNext())
        {
            return tail;
        }

        // There's more to come, loop back to begin render.

        return false;
    }

    // Capture BeginRender event from the formfragment or the addRowWrapper, and render the informal parameters
    // into the row.
    boolean onBeginRender(MarkupWriter writer)
    {
        resources.renderInformalParameters(writer);

        return true;
    }

    void cleanupRender(MarkupWriter writer)
    {
        if (wrapper != null)
            writer.end();

        popContext();
    }

    private void popContext()
    {
        environment.pop(AjaxFormLoopContext.class);
    }

    Object onInjectRow(EventContext context)
    {
        ComponentEventCallback callback = new ComponentEventCallback()
        {
            public boolean handleResult(Object result)
            {
                value = result;

                return true;
            }
        };

        resources.triggerContextEvent(EventConstants.ADD_ROW, context, callback);

        if (value == null)
            throw new IllegalArgumentException(String.format(
                    "Event handler for event 'addRow' from %s should have returned a non-null value.",
                    resources.getCompleteId()));

        ajaxResponseRenderer.addFilter(new PartialMarkupRendererFilter()
        {
            public void renderMarkup(MarkupWriter writer, JSONObject reply, PartialMarkupRenderer renderer)
            {
                pushContext();

                renderer.renderMarkup(writer, reply);

                popContext();
            }
        });

        return ajaxResponse;
    }

    Object onTriggerRemoveRow(@RequestParameter("t:rowvalue") String encodedValue)
    {
        syncValue(encodedValue);

        resources.triggerEvent(EventConstants.REMOVE_ROW, new Object[]
                {value}, null);

        return new JSONObject();
    }

    private void beginHeartbeat()
    {
        heartbeat.begin();
    }

    private void endHeartbeat()
    {
        heartbeat.end();
    }
}
