/*
 * 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.Attributes;
import org.apache.myfaces.tobago.internal.component.AbstractUIBadge;
import org.apache.myfaces.tobago.internal.component.AbstractUICommand;
import org.apache.myfaces.tobago.internal.component.AbstractUIFormBase;
import org.apache.myfaces.tobago.internal.component.AbstractUILink;
import org.apache.myfaces.tobago.internal.component.AbstractUISelectBooleanCheckbox;
import org.apache.myfaces.tobago.internal.component.AbstractUISelectManyCheckbox;
import org.apache.myfaces.tobago.internal.component.AbstractUISelectOneRadio;
import org.apache.myfaces.tobago.internal.component.AbstractUISeparator;
import org.apache.myfaces.tobago.internal.component.AbstractUIStyle;
import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
import org.apache.myfaces.tobago.internal.util.RenderUtils;
import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
import org.apache.myfaces.tobago.renderkit.css.CssItem;
import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
import org.apache.myfaces.tobago.renderkit.html.Arias;
import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
import org.apache.myfaces.tobago.renderkit.html.HtmlButtonTypes;
import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
import org.apache.myfaces.tobago.util.ComponentUtils;
import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.faces.component.UIComponent;
import javax.faces.component.UIParameter;
import javax.faces.context.FacesContext;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.List;

public abstract class CommandRendererBase<T extends AbstractUICommand> extends DecodingCommandRendererBase<T> {

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

  @Override
  public void encodeBeginInternal(final FacesContext facesContext, final T component) throws IOException {

    final String clientId = component.getClientId(facesContext);
    final boolean disabled = component.isDisabled();
    final LabelWithAccessKey label = new LabelWithAccessKey(component);
    final boolean anchor = (component.getLink() != null || component.getOutcome() != null) && !disabled;
    final String target = component.getTarget();
    final boolean parentOfCommands = component.isParentOfCommands();
    final boolean dropdownSubmenu = isInside(facesContext, HtmlElements.COMMAND);

    final TobagoResponseWriter writer = getResponseWriter(facesContext);

    encodeBeginOuter(facesContext, component);

    if (anchor) {
      writer.startElement(HtmlElements.A);
    } else {
      writer.startElement(HtmlElements.BUTTON);
      writer.writeAttribute(HtmlAttributes.TYPE, HtmlButtonTypes.BUTTON);
    }
    writer.writeIdAttribute(component.getFieldId(facesContext));
    writer.writeNameAttribute(clientId);
    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);

    if (!disabled) {
      if (anchor) {
        final String href = RenderUtils.generateUrl(facesContext, component);
        writer.writeAttribute(HtmlAttributes.HREF, href, true);
        writer.writeAttribute(HtmlAttributes.TARGET, target, true);

        component.setOmit(true);
      }

      if (label.getAccessKey() != null) {
        writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
        AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), clientId);
      }

      final int tabIndex = ComponentUtils.getIntAttribute(component, Attributes.tabIndex);
      if (tabIndex != 0) {
        writer.writeAttribute(HtmlAttributes.TABINDEX, tabIndex);
      }
    }

    HtmlRendererUtils.writeDataAttributes(facesContext, writer, component);

    if (parentOfCommands) {
      writer.writeAttribute(DataAttributes.TOGGLE, "dropdown", false);
    }
    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, component);
    writer.writeAttribute(HtmlAttributes.TITLE, title, true);

    writer.writeClassAttribute(
        getRendererCssClass(),
        getRendererCssClass().createMarkup(component.getMarkup()),
        getCssItems(facesContext, component),
        dropdownSubmenu ? BootstrapClass.DROPDOWN_ITEM : null,
        parentOfCommands && !dropdownSubmenu ? BootstrapClass.DROPDOWN_TOGGLE : null,
        component.getCustomClass(),
        isInside(facesContext, HtmlElements.TOBAGO_LINKS) ? BootstrapClass.NAV_LINK : null);

    final boolean defaultCommand = ComponentUtils.getBooleanAttribute(component, Attributes.defaultCommand);
    if (defaultCommand) {
      final AbstractUIFormBase form = ComponentUtils.findAncestor(component, AbstractUIFormBase.class);
      if (form != null) {
        writer.writeAttribute(DataAttributes.DEFAULT, form.getClientId(facesContext), false);
      } else {
        LOG.warn("No from found for {}", clientId);
      }
    }

    if (!disabled) {
      encodeBehavior(writer, facesContext, component);
    }

    final String image = ComponentUtils.getStringAttribute(component, Attributes.image);
    HtmlRendererUtils.encodeIconOrImage(writer, image);

    if (label.getLabel() != null) {
      writer.startElement(HtmlElements.SPAN);
      HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
      writer.endElement(HtmlElements.SPAN);
      encodeBadge(facesContext, component);
    }

    if (anchor) {
      writer.endElement(HtmlElements.A);
    } else {
      writer.endElement(HtmlElements.BUTTON);
    }
  }

  @Override
  public boolean getRendersChildren() {
    return true;
  }

  @Override
  public void encodeChildrenInternal(final FacesContext facesContext, final T component) throws IOException {
    final boolean parentOfCommands = component.isParentOfCommands();

    final TobagoResponseWriter writer = getResponseWriter(facesContext);

    if (parentOfCommands) {
      List<UIComponent> renderLater = null;

      writer.startElement(HtmlElements.DIV);
      writer.writeClassAttribute(BootstrapClass.DROPDOWN_MENU);
// fixme         isInside(facesContext, x) ? BootstrapClass.DROPDOWN_MENU_RIGHT : null);
      writer.writeAttribute(Arias.LABELLEDBY, component.getFieldId(facesContext), false);
      writer.writeAttribute(HtmlAttributes.NAME, component.getClientId(facesContext), false);

      for (final UIComponent child : component.getChildren()) {
        if (child.isRendered()
            && !(child instanceof UIParameter)
            && !(child instanceof AbstractUIBadge)) {
          if (child instanceof AbstractUIStyle) {
            if (renderLater == null) {
              renderLater = new ArrayList<>();
            }
            renderLater.add(child);
          } else if (child instanceof AbstractUILink
              || child instanceof AbstractUISelectBooleanCheckbox
              || child instanceof AbstractUISelectManyCheckbox
              || child instanceof AbstractUISelectOneRadio
              || child instanceof AbstractUISeparator) {
            insideBegin(facesContext, HtmlElements.COMMAND); // XXX may refactor / cleanup
            child.encodeAll(facesContext);
            insideEnd(facesContext, HtmlElements.COMMAND); // XXX may refactor / cleanup
          } else {
            writer.startElement(HtmlElements.DIV);
            writer.writeClassAttribute(BootstrapClass.DROPDOWN_ITEM);
            child.encodeAll(facesContext);
            writer.endElement(HtmlElements.DIV);
          }
        }
      }
      writer.endElement(HtmlElements.DIV);

      if (renderLater != null) {
        for (UIComponent child : renderLater) {
          child.encodeAll(facesContext);
        }
      }
    } else {
      for (final UIComponent child : component.getChildren()) {
        if (!(child instanceof AbstractUIBadge)) {
          child.encodeAll(facesContext);
        }
      }
    }
  }

  @Override
  public void encodeEndInternal(final FacesContext facesContext, final T component) throws IOException {
    encodeEndOuter(facesContext, component);
  }

  protected void encodeBeginOuter(final FacesContext facesContext, final T command) throws IOException {

    final String clientId = command.getClientId(facesContext);
    final boolean parentOfCommands = command.isParentOfCommands();
    final boolean dropdownSubmenu = isInside(facesContext, HtmlElements.COMMAND);
    final TobagoResponseWriter writer = getResponseWriter(facesContext);

    if (parentOfCommands) {
      writer.startElement(HtmlElements.TOBAGO_DROPDOWN);
      writer.writeIdAttribute(clientId);

      writer.writeClassAttribute(dropdownSubmenu ? TobagoClass.DROPDOWN__SUBMENU : BootstrapClass.DROPDOWN);
    }
  }

  protected void encodeEndOuter(final FacesContext facesContext, final T command) throws IOException {
    final TobagoResponseWriter writer = getResponseWriter(facesContext);
    if (command.isParentOfCommands()) {
      writer.endElement(HtmlElements.TOBAGO_DROPDOWN);
    }
  }

  protected CssItem[] getOuterCssItems(final FacesContext facesContext, final T command) {
    return null;
  }

  abstract TobagoClass getRendererCssClass();

  protected CssItem[] getCssItems(final FacesContext facesContext, final T command) {
    return null;
  }

  protected void encodeBadge(final FacesContext facesContext, final T command) throws IOException {
  }
}
