/*
 * 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.internal.renderkit.renderer;

import org.apache.myfaces.tobago.component.ClientBehaviors;
import org.apache.myfaces.tobago.internal.behavior.EventBehavior;
import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
import org.apache.myfaces.tobago.internal.component.AbstractUIEvent;
import org.apache.myfaces.tobago.internal.component.AbstractUIOperation;
import org.apache.myfaces.tobago.internal.renderkit.Collapse;
import org.apache.myfaces.tobago.internal.renderkit.Command;
import org.apache.myfaces.tobago.internal.renderkit.CommandMap;
import org.apache.myfaces.tobago.internal.util.RenderUtils;
import org.apache.myfaces.tobago.internal.util.StringUtils;
import org.apache.myfaces.tobago.util.ComponentUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.faces.component.ActionSource;
import javax.faces.component.EditableValueHolder;
import javax.faces.component.UIComponent;
import javax.faces.component.behavior.AjaxBehavior;
import javax.faces.component.behavior.ClientBehavior;
import javax.faces.component.behavior.ClientBehaviorContext;
import javax.faces.context.FacesContext;
import javax.faces.event.AjaxBehaviorEvent;
import javax.faces.event.PhaseId;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

public class TobagoClientBehaviorRenderer extends javax.faces.render.ClientBehaviorRenderer {

  private static final Logger LOG = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

  /**
   * In standard JSF this method returns a JavaScript string. Because of CSP, Tobago doesn't render JavaScript
   * into the HTML content. It transports the return value a bit hacky by {@link CommandMap#storeCommandMap}.
   *
   * @return "dummy" string or null, if nothing to do.
   */
  @Override
  public String getScript(final ClientBehaviorContext behaviorContext, final ClientBehavior behavior) {

    final FacesContext facesContext = behaviorContext.getFacesContext();
    final UIComponent uiComponent = behaviorContext.getComponent();
    final ClientBehaviors eventName = ClientBehaviors.valueOf(behaviorContext.getEventName());

    //// TBD: is this nice? May be implemented with a JSF behavior?
    Collapse collapse = createCollapsible(facesContext, uiComponent);

    String executeIds = null;
    String renderIds = null;
    Boolean transition = null;
    String target = null;
    String actionId = null;
    boolean omit = false;
    final String confirmation = ComponentUtils.getConfirmation(uiComponent);
    if (behavior instanceof AjaxBehavior) {
      final AjaxBehavior ajaxBehavior = (AjaxBehavior) behavior;
      if (ajaxBehavior.isDisabled()) {
        return null;
      }
      final Collection<String> execute = ajaxBehavior.getExecute();
      final Collection<String> render = ajaxBehavior.getRender();
      final String clientId = uiComponent.getClientId(facesContext);

      executeIds = ComponentUtils.evaluateClientIds(facesContext, uiComponent, execute.toArray(new String[0]));
      if (executeIds != null) {
        executeIds = executeIds + " " + clientId;
      } else {
        executeIds = clientId;
      }
      if (uiComponent instanceof AbstractUICommand) { // <f:ajax> inside of a command
        final AbstractUICommand command = (AbstractUICommand) uiComponent;
        transition = command.isTransition();
        target = command.getTarget();
        omit = command.isOmit() || StringUtils.isNotBlank(RenderUtils.generateUrl(facesContext, command));
      }
      renderIds = ComponentUtils.evaluateClientIds(facesContext, uiComponent, render.toArray(new String[0]));
      actionId = clientId;
    } else if (behavior instanceof EventBehavior) { // <tc:event>
      final EventBehavior eventBehavior = (EventBehavior) behavior;
      final AbstractUIEvent event = RenderUtils.getAbstractUIEvent(uiComponent, eventBehavior);

      if (event != null) {
        if (!event.isRendered() || event.isDisabled()) {
          return null;
        } else {
          transition = event.isTransition();
          target = event.getTarget();
          actionId = event.getClientId(facesContext);
          if (collapse == null) {
            collapse = createCollapsible(facesContext, event);
          }
          omit = event.isOmit() || StringUtils.isNotBlank(RenderUtils.generateUrl(facesContext, event));
        }
      }
    } else {
      LOG.warn("Unknown behavior '{}'!", behavior.getClass().getName());
    }

    final Command command = new Command(
        actionId,
        transition,
        target,
        executeIds,
        renderIds,
        null,
        confirmation,
        null,
        collapse,
        omit);

    final CommandMap map = new CommandMap();
    map.addCommand(eventName, command);
    CommandMap.storeCommandMap(facesContext, map);

    // XXX the return value is a string, but we should use a CommandMap
    return "dummy";
  }

  @Override
  public void decode(final FacesContext facesContext, final UIComponent component,
      final ClientBehavior clientBehavior) {
    if (clientBehavior instanceof AjaxBehavior) {
      AjaxBehavior ajaxBehavior = (AjaxBehavior) clientBehavior;
      if (!component.isRendered() || ajaxBehavior.isDisabled()) {
        return;
      }

      dispatchBehaviorEvent(component, ajaxBehavior);
    } else if (clientBehavior instanceof EventBehavior) {
      final EventBehavior eventBehavior = (EventBehavior) clientBehavior;
      final AbstractUIEvent abstractUIEvent = RenderUtils.getAbstractUIEvent(component, eventBehavior);

      if (!component.isRendered() || abstractUIEvent == null
          || !abstractUIEvent.isRendered() || abstractUIEvent.isDisabled()) {
        return;
      }

      for (List<ClientBehavior> children : abstractUIEvent.getClientBehaviors().values()) {
        for (ClientBehavior child : children) {
          decode(facesContext, component, child);
        }
      }
      dispatchBehaviorEvent(component, eventBehavior);
    }
  }

  private void dispatchBehaviorEvent(final UIComponent component, final ClientBehavior clientBehavior) {
    final AjaxBehaviorEvent event = new AjaxBehaviorEvent(component, clientBehavior);
    final boolean isImmediate = isImmediate(clientBehavior, component);
    event.setPhaseId(isImmediate ? PhaseId.APPLY_REQUEST_VALUES : PhaseId.INVOKE_APPLICATION);
    component.queueEvent(event);
  }

  private boolean isImmediate(final ClientBehavior clientBehavior, final UIComponent component) {
    if (clientBehavior instanceof AjaxBehavior) {
      AjaxBehavior ajaxBehavior = (AjaxBehavior) clientBehavior;
      if (ajaxBehavior.isImmediateSet()) {
        return ajaxBehavior.isImmediate();
      }
    } else if (clientBehavior instanceof EventBehavior) {
      EventBehavior eventBehavior = (EventBehavior) clientBehavior;
      if (eventBehavior.isImmediateSet()) {
        return eventBehavior.isImmediate();
      }
    }
    if (component instanceof EditableValueHolder) {
      return ((EditableValueHolder) component).isImmediate();
    }
    if (component instanceof ActionSource) {
      return ((ActionSource) component).isImmediate();
    }
    return false;
  }

  /**
   * @deprecated TBD
   */
  @Deprecated
  public static Collapse createCollapsible(final FacesContext facesContext, final UIComponent component) {
    //// TBD: is this nice? May be implemented with a JSF behavior?
    //// BEGIN

    // XXX too complicated
    final List<AbstractUIOperation> operations = new ArrayList<>();
    for (final UIComponent child : component.getChildren()) {
      if (AbstractUIOperation.class.isAssignableFrom(child.getClass())) {
        operations.add((AbstractUIOperation) child);
      }
    }

    Collapse collapse = null;
    if (operations.size() > 0) {
      final AbstractUIOperation operation = operations.get(0);
      final String forId = ComponentUtils.evaluateClientId(facesContext, component, operation.getFor());
      collapse = new Collapse(Collapse.Action.valueOf(operation.getName()), forId);
    }

    //// TBD: is this nice?
    //// END
    return collapse;
  }

}
