/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.myfaces.tobago.facelets;

import org.apache.myfaces.tobago.component.Attributes;
import org.apache.myfaces.tobago.component.ClientBehaviors;
import org.apache.myfaces.tobago.component.UIEvent;
import org.apache.myfaces.tobago.internal.behavior.EventBehavior;
import org.apache.myfaces.tobago.internal.component.AbstractUIEvent;

import javax.el.MethodExpression;
import javax.faces.component.PartialStateHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.ClientBehaviorHolder;
import javax.faces.context.FacesContext;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.AjaxBehaviorListener;
import javax.faces.view.BehaviorHolderAttachedObjectHandler;
import javax.faces.view.facelets.ComponentConfig;
import javax.faces.view.facelets.ComponentHandler;
import javax.faces.view.facelets.FaceletContext;
import javax.faces.view.facelets.TagAttribute;
import javax.faces.view.facelets.TagAttributeException;
import javax.faces.view.facelets.TagException;
import java.io.IOException;

/**
 * This tag creates an instance of AjaxBehavior, and associates it with the nearest
 * parent UIComponent that implements ClientBehaviorHolder interface. This tag can
 * be used on single or composite components.
 * <p>
 * Unless otherwise specified, all attributes accept static values or EL expressions.
 * </p>
 * <p>
 * According to the documentation, the tag handler implementing this tag should meet
 * the following conditions:
 * </p>
 * <ul>
 * <li>Since this tag attach objects to UIComponent instances, and those instances
 * implements Behavior interface, this component should implement
 * BehaviorHolderAttachedObjectHandler interface.</li>
 * <li>f:ajax does not support binding property. In theory we should do something similar
 * to f:convertDateTime tag does: extends from ConverterHandler and override setAttributes
 * method, but in this case BehaviorTagHandlerDelegate has binding property defined, so
 * if we extend from BehaviorHandler we add binding support to f:ajax.</li>
 * <li>This tag works as a attached object handler, but note on the api there is no component
 * to define a target for a behavior. See comment inside apply() method.</li>
 * </ul>
 *
 * @since 3.0.0
 */
public class EventHandler extends TobagoComponentHandler implements BehaviorHolderAttachedObjectHandler {

  public static final Class<?>[] AJAX_BEHAVIOR_LISTENER_SIG = new Class<?>[]{AjaxBehaviorEvent.class};

  private final TagAttribute event;

// todo (see original AjaxHandler impl)  private final boolean _wrapMode;

  public EventHandler(final ComponentConfig config) {
    super(config);
    event = getAttribute(Attributes.event.getName());
  }

  @Override
  public void apply(final FaceletContext ctx, final UIComponent parent)
      throws IOException {

    super.apply(ctx, parent);

    //Apply only if we are creating a new component
    if (!ComponentHandler.isNew(parent)) {
      return;
    }
    if (parent instanceof ClientBehaviorHolder) {
      //Apply this handler directly over the parent
      applyAttachedObject(ctx.getFacesContext(), parent);
//todo      } else if (UIComponent.isCompositeComponent(parent)) {
//todo        FaceletCompositionContext mctx = FaceletCompositionContext.getCurrentInstance(ctx);
      // It is supposed that for composite components, this tag should
      // add itself as a target, but note that on whole api does not exists
      // some tag that expose client behaviors as targets for composite
      // components. In RI, there exists a tag called composite:clientBehavior,
      // but does not appear on spec or javadoc, maybe because this could be
      // understand as an implementation detail, after all there exists a key
      // called AttachedObjectTarget.ATTACHED_OBJECT_TARGETS_KEY that could be
      // used to create a tag outside jsf implementation to attach targets.
//todo        mctx.addAttachedObjectHandler(parent, this);
    } else {
      throw new TagException(this.tag,
          "Parent is not composite component or of type ClientBehaviorHolder, type is: "
              + parent);
    }
  }

  /**
   * ViewDeclarationLanguage.retargetAttachedObjects uses it to check
   * if the the target to be processed is applicable for this handler
   */
  @Override
  public String getEventName() {
    if (event == null) {
      return null;
    } else {
      return event.getValue();
    }
  }

  /**
   * This method should create an AjaxBehavior object and attach it to the
   * parent component.
   * <p>
   * Also, it should check if the parent can apply the selected AjaxBehavior
   * to the selected component through ClientBehaviorHolder.getEventNames() or
   * ClientBehaviorHolder.getDefaultEventName()
   */
  @Override
  public void applyAttachedObject(final FacesContext context, final UIComponent parent) {
    // Retrieve the current FaceletContext from FacesContext object
    final FaceletContext faceletContext = (FaceletContext) context
        .getAttributes().get(FaceletContext.FACELET_CONTEXT_KEY);

    final ClientBehaviorHolder clientBehaviorHolder = (ClientBehaviorHolder) parent;
    final UIComponent lastChild = parent.getChildren().stream().skip(parent.getChildCount() - 1)
        .findFirst().orElse(null);
    final AbstractUIEvent abstractUIEvent = lastChild instanceof AbstractUIEvent ? (AbstractUIEvent) lastChild : null;

    if (abstractUIEvent != null) {
      String eventName = getEventName();
      if (eventName == null) {
        eventName = clientBehaviorHolder.getDefaultEventName();
        if (eventName == null) {
          throw new TagAttributeException(event, "eventName could not be defined for f:ajax tag with no wrap mode.");
        }
      } else if (!clientBehaviorHolder.getEventNames().contains(eventName)) {
        throw new TagAttributeException(event, "event it is not a valid eventName defined for this component");
      }

      final EventBehavior eventBehavior = createBehavior(context);
      eventBehavior.setFor(abstractUIEvent.getId());

      clientBehaviorHolder.addClientBehavior(eventName, eventBehavior);
    }
  }

  protected EventBehavior createBehavior(final FacesContext context) {
    return (EventBehavior) context.getApplication().createBehavior(EventBehavior.BEHAVIOR_ID);
  }

  @Override
  public void onComponentCreated(
      final FaceletContext faceletContext, final UIComponent component, final UIComponent parent) {
    super.onComponentCreated(faceletContext, component, parent);

    final UIEvent uiEvent = (UIEvent) component;
    if (uiEvent.getEvent() == null) {
      final ClientBehaviorHolder holder = (ClientBehaviorHolder) parent;
      uiEvent.setEvent(ClientBehaviors.valueOf(holder.getDefaultEventName()));
    }
  }

  /**
   * The documentation says this attribute should not be used since it is not
   * taken into account. Instead, getEventName is used on
   * ViewDeclarationLanguage.retargetAttachedObjects.
   */
  @Override
  public String getFor() {
    return null;
  }

  /**
   * Wraps a method expression in a AjaxBehaviorListener
   */
  public static final class AjaxBehaviorListenerImpl implements
      AjaxBehaviorListener, PartialStateHolder {
    private MethodExpression expression;
    private boolean transientBoolean;
    private boolean initialStateMarked;

    public AjaxBehaviorListenerImpl() {
    }

    public AjaxBehaviorListenerImpl(final MethodExpression expr) {
      expression = expr;
    }

    @Override
    public void processAjaxBehavior(final AjaxBehaviorEvent event)
        throws AbortProcessingException {
      expression.invoke(FacesContext.getCurrentInstance().getELContext(),
          new Object[]{event});
    }

    @Override
    public boolean isTransient() {
      return transientBoolean;
    }

    @Override
    public void restoreState(final FacesContext context, final Object state) {
      if (state == null) {
        return;
      }
      expression = (MethodExpression) state;
    }

    @Override
    public Object saveState(final FacesContext context) {
      if (initialStateMarked()) {
        return null;
      }
      return expression;
    }

    @Override
    public void setTransient(final boolean newTransientValue) {
      transientBoolean = newTransientValue;
    }

    @Override
    public void clearInitialState() {
      initialStateMarked = false;
    }

    @Override
    public boolean initialStateMarked() {
      return initialStateMarked;
    }

    @Override
    public void markInitialState() {
      initialStateMarked = true;
    }
  }
}
