/*
 * 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.component.ClientBehaviors;
import org.apache.myfaces.tobago.component.Facets;
import org.apache.myfaces.tobago.component.RendererTypes;
import org.apache.myfaces.tobago.component.Tags;
import org.apache.myfaces.tobago.context.Markup;
import org.apache.myfaces.tobago.event.TabChangeEvent;
import org.apache.myfaces.tobago.internal.behavior.EventBehavior;
import org.apache.myfaces.tobago.internal.component.AbstractUIEvent;
import org.apache.myfaces.tobago.internal.component.AbstractUIPanelBase;
import org.apache.myfaces.tobago.internal.component.AbstractUITab;
import org.apache.myfaces.tobago.internal.component.AbstractUITabGroup;
import org.apache.myfaces.tobago.internal.util.AccessKeyLogger;
import org.apache.myfaces.tobago.internal.util.HtmlRendererUtils;
import org.apache.myfaces.tobago.model.SwitchType;
import org.apache.myfaces.tobago.renderkit.LabelWithAccessKey;
import org.apache.myfaces.tobago.renderkit.RendererBase;
import org.apache.myfaces.tobago.renderkit.css.BootstrapClass;
import org.apache.myfaces.tobago.renderkit.css.TobagoClass;
import org.apache.myfaces.tobago.renderkit.html.CustomAttributes;
import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
import org.apache.myfaces.tobago.renderkit.html.HtmlAttributes;
import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
import org.apache.myfaces.tobago.renderkit.html.HtmlRoleValues;
import org.apache.myfaces.tobago.util.ComponentUtils;
import org.apache.myfaces.tobago.webapp.TobagoResponseWriter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.el.ValueExpression;
import javax.faces.application.FacesMessage;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.behavior.AjaxBehavior;
import javax.faces.context.FacesContext;
import javax.faces.event.ComponentSystemEvent;
import javax.faces.event.ComponentSystemEventListener;
import javax.faces.event.ListenerFor;
import javax.faces.event.PostAddToViewEvent;
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;

@ListenerFor(systemEventClass = PostAddToViewEvent.class)
public class TabGroupRenderer extends RendererBase implements ComponentSystemEventListener {

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

  private static final String INDEX_POSTFIX = ComponentUtils.SUB_SEPARATOR + "index";

  @Override
  public void processEvent(final ComponentSystemEvent event) {

    final AbstractUITabGroup tabGroup = (AbstractUITabGroup) event.getComponent();

    for (final UIComponent child : tabGroup.getChildren()) {
      if (child instanceof AbstractUITab) {
        final AbstractUITab tab = (AbstractUITab) child;
        final FacesContext facesContext = FacesContext.getCurrentInstance();
        final ClientBehaviors click = ClientBehaviors.click;
        switch (tabGroup.getSwitchType()) {
          case none:
            break;
          case client:
            // todo: implement a client behavior which can call local scripts (respect CSP)
            break;
          case reloadTab:
            final AjaxBehavior ajaxBehavior = new AjaxBehavior();
            final Collection<String> ids = Collections.singleton(
                UINamingContainer.getSeparatorChar(facesContext) + tabGroup.getClientId(facesContext));
            ajaxBehavior.setExecute(ids);
            ajaxBehavior.setRender(ids);
            tab.addClientBehavior(click.name(), ajaxBehavior);
            break;
          case reloadPage:
            final AbstractUIEvent component = (AbstractUIEvent) ComponentUtils.createComponent(
                facesContext, Tags.event.componentType(), RendererTypes.Event, "_click");
            component.setEvent(click);
            tab.getChildren().add(component);
            final EventBehavior eventBehavior = new EventBehavior();
            eventBehavior.setFor(component.getId());
            tab.addClientBehavior(click.name(), eventBehavior);
            break;
          default:
            LOG.error("Unknown switch type: '{}'", tabGroup.getSwitchType());
        }
      }
    }
  }

  @Override
  public void decode(final FacesContext facesContext, final UIComponent component) {
    if (ComponentUtils.isOutputOnly(component)) {
      return;
    }

    final int oldIndex = ((AbstractUITabGroup) component).getRenderedIndex();

    final String clientId = component.getClientId(facesContext);
    final Map parameters = facesContext.getExternalContext().getRequestParameterMap();
    final String newValue = (String) parameters.get(clientId + INDEX_POSTFIX);
    try {
      final int newIndex = Integer.parseInt(newValue);
      if (newIndex != oldIndex) {
        final TabChangeEvent event = new TabChangeEvent(component, oldIndex, newIndex);
        component.queueEvent(event);
      }
    } catch (final NumberFormatException e) {
      LOG.error("Can't parse newIndex: '" + newValue + "'");
    }
  }

  @Override
  public void encodeEnd(final FacesContext facesContext, final UIComponent uiComponent) throws IOException {

    final AbstractUITabGroup tabGroup = (AbstractUITabGroup) uiComponent;
    final int selectedIndex = ensureRenderedSelectedIndex(facesContext, tabGroup);
    final String clientId = tabGroup.getClientId(facesContext);
    final String hiddenId = clientId + TabGroupRenderer.INDEX_POSTFIX;
    final SwitchType switchType = tabGroup.getSwitchType();
    final Markup markup = tabGroup.getMarkup();
    final TobagoResponseWriter writer = getResponseWriter(facesContext);

    writer.startElement(HtmlElements.TOBAGO_TAB_GROUP);
    writer.writeIdAttribute(clientId);
    writer.writeClassAttribute(
        BootstrapClass.CARD,
        TobagoClass.TAB_GROUP.createMarkup(markup),
        tabGroup.getCustomClass(),
        markup != null && markup.contains(Markup.SPREAD) ? TobagoClass.SPREAD : null);
    HtmlRendererUtils.writeDataAttributes(facesContext, writer, tabGroup);
    writer.writeAttribute(CustomAttributes.SWITCH_TYPE, switchType.name(), false);

    encodeBehavior(writer, facesContext, tabGroup);

    writer.startElement(HtmlElements.INPUT);
    writer.writeAttribute(HtmlAttributes.TYPE, HtmlInputTypes.HIDDEN);
    writer.writeAttribute(HtmlAttributes.VALUE, selectedIndex);
    writer.writeNameAttribute(hiddenId);
    writer.writeIdAttribute(hiddenId);
    writer.endElement(HtmlElements.INPUT);

    if (tabGroup.isShowNavigationBar()) {
      encodeHeader(facesContext, writer, tabGroup, selectedIndex, switchType);
    }

    encodeContent(facesContext, writer, tabGroup, selectedIndex, switchType);

    writer.endElement(HtmlElements.TOBAGO_TAB_GROUP);
  }

  private int ensureRenderedSelectedIndex(final FacesContext context, final AbstractUITabGroup tabGroup) {
    final int selectedIndex = tabGroup.getSelectedIndex();
    // ensure to select a rendered tab
    int index = -1;
    int closestRenderedTabIndex = -1;
    for (final UIComponent tab : tabGroup.getChildren()) {
      if (tab instanceof AbstractUIPanelBase) {
        index++;
        if (index == selectedIndex) {
          if (tab.isRendered()) {
            return index;
          } else if (closestRenderedTabIndex > -1) {
            break;
          }
        }
        if (tab.isRendered()) {
          closestRenderedTabIndex = index;
          if (index > selectedIndex) {
            break;
          }
        }
      }
    }
    if (closestRenderedTabIndex == -1) {
      // resetting index to 0
      closestRenderedTabIndex = 0;
    }
    final ValueExpression expression = tabGroup.getValueExpression(Attributes.selectedIndex.getName());
    if (expression != null) {
      expression.setValue(context.getELContext(), closestRenderedTabIndex);
    } else {
      tabGroup.setSelectedIndex(closestRenderedTabIndex);
    }
    return closestRenderedTabIndex;
  }

  private void encodeHeader(
      final FacesContext facesContext, final TobagoResponseWriter writer, final AbstractUITabGroup tabGroup,
      final int selectedIndex, final SwitchType switchType)
      throws IOException {

    final String tabGroupClientId = tabGroup.getClientId(facesContext);

    writer.startElement(HtmlElements.DIV);
    writer.writeClassAttribute(BootstrapClass.CARD_HEADER);
    writer.startElement(HtmlElements.UL);
    writer.writeClassAttribute(
        BootstrapClass.NAV,
        BootstrapClass.NAV_TABS,
        BootstrapClass.CARD_HEADER_TABS);
    writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TABLIST.toString(), false);

    int index = 0;
    for (final UIComponent child : tabGroup.getChildren()) {
      if (child instanceof AbstractUITab) {
        final AbstractUITab tab = (AbstractUITab) child;
        if (tab.isRendered()) {
          final LabelWithAccessKey label = new LabelWithAccessKey(tab);
          final UIComponent labelFacet = ComponentUtils.getFacet(tab, Facets.label);
          final UIComponent barFacet = ComponentUtils.getFacet(tab, Facets.bar);
          final boolean disabled = tab.isDisabled();
          final String tabId = tab.getClientId(facesContext);
          Markup markup = tab.getMarkup() != null ? tab.getMarkup() : Markup.NULL;

          final FacesMessage.Severity maxSeverity
              = ComponentUtils.getMaximumSeverityOfChildrenMessages(facesContext, tab);
          if (maxSeverity != null) {
            markup = markup.add(ComponentUtils.markupOfSeverity(maxSeverity));
          }

          writer.startElement(HtmlElements.TOBAGO_TAB);
          writer.writeIdAttribute(tabId);
          writer.writeClassAttribute(
              BootstrapClass.NAV_ITEM,
              TobagoClass.TAB.createMarkup(markup),
              barFacet != null ? TobagoClass.TAB__BAR_FACET : null,
              tab.getCustomClass());
          writer.writeAttribute(HtmlAttributes.FOR, tabGroupClientId, true);
          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.PRESENTATION.toString(), false);
          writer.writeAttribute(CustomAttributes.INDEX, index);
          final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, tab);
          if (title != null) {
            writer.writeAttribute(HtmlAttributes.TITLE, title, true);
          }

          writer.startElement(HtmlElements.A);
          if (!tab.isDisabled()) {
            writer.writeAttribute(DataAttributes.TOGGLE, "tab", false);
          }
          if (tab.isDisabled()) {
            writer.writeClassAttribute(BootstrapClass.NAV_LINK, BootstrapClass.DISABLED);
          } else if (selectedIndex == index) {
            writer.writeClassAttribute(BootstrapClass.NAV_LINK, BootstrapClass.ACTIVE);
          } else {
            writer.writeClassAttribute(BootstrapClass.NAV_LINK);
          }
          if (!disabled && switchType == SwitchType.client) {
            writer.writeAttribute(HtmlAttributes.HREF, '#' + getTabPanelId(facesContext, tab), false);
            writer.writeAttribute(
                DataAttributes.TARGET, '#' + getTabPanelId(facesContext, tab).replaceAll(":", "\\\\:"), false);
          }

          if (!disabled && label.getAccessKey() != null) {
            writer.writeAttribute(HtmlAttributes.ACCESSKEY, Character.toString(label.getAccessKey()), false);
            AccessKeyLogger.addAccessKey(facesContext, label.getAccessKey(), tabId);
          }
          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TAB.toString(), false);

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

          boolean labelEmpty = true;
          final String image = tab.getImage();
          // tab.getImage() resolves to empty string if el-expression resolves to null
          if (image != null && !image.isEmpty()) {
            writer.startElement(HtmlElements.IMG);
            writer.writeAttribute(HtmlAttributes.SRC, image, true);
// TBD      writer.writeClassAttribute(Classes.create(tab, (label.getLabel() != null? "image-right-margin" : "image")));
            writer.endElement(HtmlElements.IMG);
            labelEmpty = false;
          }
          if (label.getLabel() != null) {
            HtmlRendererUtils.writeLabelWithAccessKey(writer, label);
            labelEmpty = false;
          }
          if (labelFacet != null) {
            labelFacet.encodeAll(facesContext);
            labelEmpty = false;
          }
          if (labelEmpty) {
            writer.writeText(Integer.toString(index + 1));
          }
          writer.endElement(HtmlElements.A);

          if (barFacet != null) {
            writer.startElement(HtmlElements.DIV);
            barFacet.encodeAll(facesContext);
            writer.endElement(HtmlElements.DIV);
          }

          writer.endElement(HtmlElements.TOBAGO_TAB);
        }
        index++;
      }
    }
    writer.endElement(HtmlElements.UL);
    writer.endElement(HtmlElements.DIV);
  }

  protected void encodeContent(
      final FacesContext facesContext, final TobagoResponseWriter writer, final AbstractUITabGroup tabGroup,
      final int selectedIndex, final SwitchType switchType) throws IOException {
    writer.startElement(HtmlElements.DIV);
    writer.writeClassAttribute(BootstrapClass.CARD_BODY, BootstrapClass.TAB_CONTENT);
    int index = 0;
    for (final UIComponent child : tabGroup.getChildren()) {
      if (child instanceof AbstractUITab) {
        final AbstractUITab tab = (AbstractUITab) child;
        if (tab.isRendered() && (switchType == SwitchType.client || index == selectedIndex) && !tab.isDisabled()) {
          final Markup markup = tab.getMarkup();

          writer.startElement(HtmlElements.TOBAGO_TAB_CONTENT);
          writer.writeClassAttribute(
              BootstrapClass.TAB_PANE,
              TobagoClass.TAB__CONTENT.createMarkup(markup),
              index == selectedIndex ? BootstrapClass.ACTIVE : null);
          writer.writeAttribute(HtmlAttributes.ROLE, HtmlRoleValues.TABPANEL.toString(), false);
          writer.writeIdAttribute(getTabPanelId(facesContext, tab));

          writer.writeAttribute(CustomAttributes.INDEX, index);

          tab.encodeAll(facesContext);

          writer.endElement(HtmlElements.TOBAGO_TAB_CONTENT);
        }
        index++;
      }
    }
    writer.endElement(HtmlElements.DIV);
  }

  private String getTabPanelId(final FacesContext facesContext, final AbstractUITab tab) {
    return tab.getClientId(facesContext) + ComponentUtils.SUB_SEPARATOR + "content";
  }
}
