/*
 * 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.util;

import org.apache.myfaces.tobago.component.Attributes;
import org.apache.myfaces.tobago.component.Facets;
import org.apache.myfaces.tobago.component.RendererTypes;
import org.apache.myfaces.tobago.component.Visual;
import org.apache.myfaces.tobago.context.Markup;
import org.apache.myfaces.tobago.context.TransientStateHolder;
import org.apache.myfaces.tobago.internal.component.AbstractUIForm;
import org.apache.myfaces.tobago.internal.component.AbstractUIFormBase;
import org.apache.myfaces.tobago.internal.component.AbstractUIInput;
import org.apache.myfaces.tobago.internal.component.AbstractUIPage;
import org.apache.myfaces.tobago.internal.component.AbstractUIPopup;
import org.apache.myfaces.tobago.internal.component.AbstractUIReload;
import org.apache.myfaces.tobago.internal.component.AbstractUISheet;
import org.apache.myfaces.tobago.internal.util.StringUtils;
import org.apache.myfaces.tobago.renderkit.RendererBase;
import org.apache.myfaces.tobago.renderkit.html.DataAttributes;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.el.ValueExpression;
import javax.faces.FactoryFinder;
import javax.faces.application.FacesMessage;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIComponent;
import javax.faces.component.UIInput;
import javax.faces.component.UINamingContainer;
import javax.faces.component.UIParameter;
import javax.faces.component.UISelectMany;
import javax.faces.component.UIViewRoot;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.event.ActionEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.render.RenderKit;
import javax.faces.render.RenderKitFactory;
import javax.faces.render.Renderer;
import javax.faces.view.facelets.FaceletContext;
import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

public final class ComponentUtils {

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

  public static final String SUB_SEPARATOR = "::";

  private static final String RENDER_KEY_PREFIX
      = "org.apache.myfaces.tobago.util.ComponentUtils.RendererKeyPrefix_";

  private static final String PAGE_KEY = "org.apache.myfaces.tobago.Page.Key";

  public static final Class[] ACTION_ARGS = {};
  public static final Class[] ACTION_LISTENER_ARGS = {ActionEvent.class};
  public static final Class[] VALUE_CHANGE_LISTENER_ARGS = {ValueChangeEvent.class};
  public static final Class[] VALIDATOR_ARGS = {FacesContext.class, UIComponent.class, Object.class};
  public static final String LIST_SEPARATOR_CHARS = ", ";

  /**
   * Name of the map for data attributes in components. New in JSF 2.2.
   *
   * @since 2.0.0
   */
  public static final String DATA_ATTRIBUTES_KEY = "javax.faces.component.DATA_ATTRIBUTES_KEY";

  private ComponentUtils() {
  }

  /**
   * @deprecated since 3.0.1
   */
  @Deprecated
  public static boolean hasErrorMessages(final FacesContext context) {
    for (final FacesMessage message : (Iterable<FacesMessage>) context::getMessages) {
      if (FacesMessage.SEVERITY_ERROR.compareTo(message.getSeverity()) <= 0) {
        return true;
      }
    }
    return false;
  }

  public static String getFacesMessageAsString(final FacesContext facesContext, final UIComponent component) {
    final Iterator messages = facesContext.getMessages(
        component.getClientId(facesContext));
    final StringBuilder stringBuffer = new StringBuilder();
    while (messages.hasNext()) {
      final FacesMessage message = (FacesMessage) messages.next();
      stringBuffer.append(message.getDetail());
    }
    if (stringBuffer.length() > 0) {
      return stringBuffer.toString();
    } else {
      return null;
    }
  }

  /**
   * @deprecated since 3.0.1
   */
  @Deprecated
  public static boolean isInPopup(final UIComponent component) {
    UIComponent c = component;
    while (c != null) {
      if (c instanceof AbstractUIPopup) {
        return true;
      }
      c = c.getParent();
    }
    return false;
  }

  /**
   * @deprecated since 3.0.1
   */
  @Deprecated
  public static void resetPage(final FacesContext context) {
    final UIViewRoot view = context.getViewRoot();
    if (view != null) {
      view.getAttributes().remove(PAGE_KEY);
    }
  }

  /**
   * Tries to walk up the parents to find the UIViewRoot, if not found, then go to FaceletContext's FacesContext for the
   * view root.
   */
  public static UIViewRoot findViewRoot(final FaceletContext faceletContext, final UIComponent component) {
    final UIViewRoot viewRoot = findAncestor(component, UIViewRoot.class);
    if (viewRoot != null) {
      return viewRoot;
    } else {
      return faceletContext.getFacesContext().getViewRoot();
    }
  }

  public static AbstractUIPage findPage(final FacesContext context, final UIComponent component) {
    final UIViewRoot view = context.getViewRoot();
    if (view != null) {
      TransientStateHolder stateHolder = (TransientStateHolder) view.getAttributes().get(PAGE_KEY);
      if (stateHolder == null || stateHolder.isEmpty()) {
        final AbstractUIPage page = findPage(component);
        stateHolder = new TransientStateHolder(page);
        context.getViewRoot().getAttributes().put(PAGE_KEY, stateHolder);
      }
      return (AbstractUIPage) stateHolder.get();
    } else {
      return findPage(component);
    }
  }

  public static AbstractUIPage findPage(final UIComponent component) {
    UIComponent c = component;
    if (c instanceof UIViewRoot) {
      return findPageBreadthFirst(c);
    } else {
      while (c != null) {
        if (c instanceof AbstractUIPage) {
          return (AbstractUIPage) c;
        }
        c = c.getParent();
      }
      return null;
    }
  }

  public static AbstractUIPage findPage(final FacesContext facesContext) {
    return findPageBreadthFirst(facesContext.getViewRoot());
  }

  private static AbstractUIPage findPageBreadthFirst(final UIComponent component) {
    for (final UIComponent child : component.getChildren()) {
      if (child instanceof AbstractUIPage) {
        return (AbstractUIPage) child;
      }
    }
    for (final UIComponent child : component.getChildren()) {
      final AbstractUIPage result = findPageBreadthFirst(child);
      if (result != null) {
        return result;
      }
    }
    return null;
  }

  public static AbstractUIFormBase findForm(final UIComponent component) {
    UIComponent c = component;
    while (c != null) {
      if (c instanceof AbstractUIFormBase) {
        return (AbstractUIFormBase) c;
      }
      c = c.getParent();
    }
    return null;
  }

  public static <T> T findAncestor(final UIComponent component, final Class<T> type) {
    UIComponent c = component;
    while (c != null) {
      if (type.isAssignableFrom(c.getClass())) {
        return (T) c;
      }
      c = c.getParent();
    }
    return null;
  }

  /**
   * Find all sub forms of a component, and collects it. It does not find sub forms of sub forms.
   */
  public static List<AbstractUIForm> findSubForms(final UIComponent component) {
    final List<AbstractUIForm> collect = new ArrayList<>();
    findSubForms(collect, component);
    return collect;
  }

  @SuppressWarnings("unchecked")
  private static void findSubForms(final List<AbstractUIForm> collect, final UIComponent component) {
    final Iterator<UIComponent> kids = component.getFacetsAndChildren();
    while (kids.hasNext()) {
      final UIComponent child = kids.next();
      if (child instanceof AbstractUIForm) {
        collect.add((AbstractUIForm) child);
      } else {
        findSubForms(collect, child);
      }
    }
  }

  /**
   * Searches the component tree beneath the component and return the first component matching the type.
   */
  public static <T extends UIComponent> T findDescendant(final UIComponent component, final Class<T> type) {

    for (final UIComponent child : component.getChildren()) {
      if (type.isAssignableFrom(child.getClass())) {
        return (T) child;
      }
      final T descendant = findDescendant(child, type);
      if (descendant != null) {
        return descendant;
      }
    }
    return null;
  }

  /**
   * Searches the component tree beneath the component and return the first component matching the type.
   */
  public static <T extends UIComponent> T findFacetDescendant(
      final UIComponent component, final Facets facet, final Class<T> type) {

    final UIComponent facetComponent = component.getFacet(facet.name());
    if (facetComponent != null) {
      if (type.isAssignableFrom(facetComponent.getClass())) {
        return (T) facetComponent;
      } else {
        return findDescendant(facetComponent, type);
      }
    } else {
      return null;
    }
  }

  /**
   * Searches the children beneath the component and return the first component matching the type.
   */
  public static <T extends UIComponent> T findChild(final UIComponent component, final Class<T> type) {

    for (final UIComponent child : component.getChildren()) {
      if (type.isAssignableFrom(child.getClass())) {
        return (T) child;
      }
    }
    return null;
  }

  /**
   * Searches the component tree beneath the component and return all component matching the type.
   */
  public static <T extends UIComponent> List<T> findDescendantList(final UIComponent component, final Class<T> type) {

    final List<T> result = new ArrayList<>();

    for (final UIComponent child : component.getChildren()) {
      if (type.isAssignableFrom(child.getClass())) {
        result.add((T) child);
      }
      result.addAll(findDescendantList(child, type));
    }
    return result;
  }

  /**
   * Looks for the attribute "for" in the component. If there is any search for the component which is referenced by the
   * "for" attribute, and return their clientId. If there is no "for" attribute, return the "clientId" of the parent (if
   * it has a parent). This is useful for labels.
   */
  public static String findClientIdFor(final UIComponent component, final FacesContext facesContext) {
    final UIComponent forComponent = findFor(component);
    if (forComponent != null) {
      final String clientId = forComponent.getClientId(facesContext);
      if (LOG.isDebugEnabled()) {
        LOG.debug("found clientId: '" + clientId + "'");
      }
      return clientId;
    }
    if (LOG.isDebugEnabled()) {
      LOG.debug("found no clientId");
    }
    return null;
  }

  public static UIComponent findFor(final UIComponent component) {
    final String forValue = getStringAttribute(component, Attributes.forValue);
    if (forValue == null) {
      return component.getParent();
    }
    return ComponentUtils.findComponent(component, forValue);
  }

  /**
   * Looks for the attribute "for" of the component. In case that the value is equals to "@auto" the children of the
   * parent will be checked if they are of the type of the parameter clazz. The "id" of the first one will be used to
   * reset the "for" attribute of the component.
   */
  public static void evaluateAutoFor(final UIComponent component, final Class<? extends UIComponent> clazz) {
    final String forComponent = getStringAttribute(component, Attributes.forValue);
    if (LOG.isDebugEnabled()) {
      LOG.debug("for = '" + forComponent + "'");
    }
    if ("@auto".equals(forComponent)) {
      // parent
      for (final UIComponent child : component.getParent().getChildren()) {
        if (setForToInput(component, child, clazz, component instanceof NamingContainer)) {
          return;
        }
      }
      // grand parent
      for (final UIComponent child : component.getParent().getParent().getChildren()) {
        if (setForToInput(component, child, clazz, component.getParent() instanceof NamingContainer)) {
          return;
        }
      }
    }
  }

  private static boolean setForToInput(
      final UIComponent component, final UIComponent child, final Class<? extends UIComponent> clazz,
      final boolean namingContainer) {
    if (clazz.isAssignableFrom(child.getClass())) { // find the matching component
      final String forComponent;
      if (namingContainer) {
        forComponent = ":::" + child.getId();
      } else {
        forComponent = child.getId();
      }
      ComponentUtils.setAttribute(component, Attributes.forValue, forComponent);
      return true;
    }
    return false;
  }

  /**
   * @deprecated since 4.0.0
   */
  @Deprecated
  public static boolean isInActiveForm(final UIComponent component) {
    UIComponent c = component;
    while (c != null) {
      if (c instanceof AbstractUIFormBase) {
        final AbstractUIFormBase form = (AbstractUIFormBase) c;
        if (form.isSubmitted()) {
          return true;
        }
      }
      c = c.getParent();
    }
    return false;
  }

  public static FacesMessage.Severity getMaximumSeverity(final UIComponent component) {
    final FacesContext facesContext = FacesContext.getCurrentInstance();
    final List<FacesMessage> messages = facesContext.getMessageList(component.getClientId(facesContext));
    final FacesMessage.Severity maximumSeverity = getMaximumSeverity(messages);

    final boolean invalid = component instanceof UIInput && !((UIInput) component).isValid();

    return invalid
        && (maximumSeverity == null || FacesMessage.SEVERITY_ERROR.getOrdinal() > maximumSeverity.getOrdinal())
        ? FacesMessage.SEVERITY_ERROR : maximumSeverity;
  }

  public static FacesMessage.Severity getMaximumSeverity(final List<FacesMessage> messages) {
    FacesMessage.Severity max = null;
    for (final FacesMessage message : messages) {
      if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) {
        max = message.getSeverity();
      }
    }
    return max;
  }

  /**
   * @deprecated since 5.0.0
   */
  @Deprecated
  public static boolean isError(final UIInput uiInput) {
    final FacesContext facesContext = FacesContext.getCurrentInstance();
    return !uiInput.isValid()
        || facesContext.getMessages(uiInput.getClientId(facesContext)).hasNext();
  }

  /**
   * @deprecated since 5.0.0
   */
  @Deprecated
  public static boolean isError(final UIComponent component) {
    if (component instanceof AbstractUIInput) {
      return isError((AbstractUIInput) component);
    }
    return false;
  }

  /**
   * @deprecated since 5.0.0
   */
  @Deprecated
  public static boolean isOutputOnly(final UIComponent component) {
    return getBooleanAttribute(component, Attributes.disabled)
        || getBooleanAttribute(component, Attributes.readonly);
  }

  public static Object getAttribute(final UIComponent component, final Attributes name) {
    return component.getAttributes().get(name.getName());
  }

  public static boolean getBooleanAttribute(final UIComponent component, final Attributes name) {
    return getBooleanAttribute(component, name, false);
  }

  public static boolean getBooleanAttribute(
      final UIComponent component, final Attributes name, final boolean defaultValue) {

    final Object bool = component.getAttributes().get(name.getName());
    if (bool == null) {
      return defaultValue;
    } else if (bool instanceof Boolean) {
      return (Boolean) bool;
    } else {
      return Boolean.valueOf(bool.toString());
    }
  }

  public static String getStringAttribute(final UIComponent component, final Attributes name) {
    return getStringAttribute(component, name, null);
  }

  public static String getStringAttribute(
      final UIComponent component, final Attributes name, final String defaultValue) {
    final String result = (String) getAttribute(component, name);
    return result != null ? result : defaultValue;
  }

  public static int getIntAttribute(final UIComponent component, final Attributes name) {
    return getIntAttribute(component, name, 0);
  }

  public static int getIntAttribute(final UIComponent component, final Attributes name, final int defaultValue) {
    final Object integer = component.getAttributes().get(name.getName());
    if (integer instanceof Number) {
      return ((Number) integer).intValue();
    } else if (integer instanceof String) {
      try {
        return Integer.parseInt((String) integer);
      } catch (final NumberFormatException e) {
        LOG.warn("Can't parse number from string : \"" + integer + "\"!");
        return defaultValue;
      }
    } else if (integer == null) {
      return defaultValue;
    } else {
      LOG.warn("Unknown type '" + integer.getClass().getName()
          + "' for integer attribute: " + name + " comp: " + component);
      return defaultValue;
    }
  }

  public static Character getCharacterAttribute(final UIComponent component, final Attributes name) {
    final Object character = getAttribute(component, name);
    if (character == null) {
      return null;
    } else if (character instanceof Character) {
      return (Character) character;
    } else if (character instanceof String) {
      final String asString = (String) character;
      return asString.length() > 0 ? asString.charAt(0) : null;
    } else {
      LOG.warn("Unknown type '" + character.getClass().getName()
          + "' for integer attribute: " + name + " comp: " + component);
      return null;
    }
  }

  public static void setAttribute(final UIComponent component, final Attributes name, final Object value) {
    component.getAttributes().put(name.getName(), value);
  }

  public static void removeAttribute(final UIComponent component, final Attributes name) {
    component.getAttributes().remove(name.getName());
  }

  public static UIComponent getFacet(final UIComponent component, final Facets facet) {
    return component.getFacet(facet.name());
  }

  public static void setFacet(final UIComponent component, final Facets facet, final UIComponent child) {
    component.getFacets().put(facet.name(), child);
  }

  public static void removeFacet(final UIComponent component, final Facets facet) {
    component.getFacets().remove(facet.name());
  }

  public static AbstractUIReload getReloadFacet(final UIComponent component) {
    final UIComponent facet = getFacet(component, Facets.reload);
    if (facet == null) {
      return null;
    } else if (facet instanceof AbstractUIReload) {
      return (AbstractUIReload) facet;
    } else {
      LOG.warn("Content of a reload facet must be {} but found {} in component with id '{}'",
          AbstractUIReload.class.getName(), facet.getClass().getName(), component.getClientId());
      return null;
    }
  }

  public static boolean isFacetOf(final UIComponent component, final UIComponent parent) {
    for (final Object o : parent.getFacets().keySet()) {
      final UIComponent facet = parent.getFacet((String) o);
      if (component.equals(facet)) {
        return true;
      }
    }
    return false;
  }

  public static RendererBase getRenderer(final FacesContext facesContext, final UIComponent component) {
    return getRenderer(facesContext, component.getFamily(), component.getRendererType());
  }

  public static RendererBase getRenderer(final FacesContext facesContext, final String family,
      final String rendererType) {
    if (rendererType == null) {
      return null;
    }

    final Map<String, Object> requestMap = facesContext.getExternalContext().getRequestMap();
    final StringBuilder key = new StringBuilder(RENDER_KEY_PREFIX);
    key.append(rendererType);
    RendererBase renderer = (RendererBase) requestMap.get(key.toString());

    if (renderer == null) {
      final Renderer myRenderer = getRendererInternal(facesContext, family, rendererType);
      if (myRenderer instanceof RendererBase) {
        requestMap.put(key.toString(), myRenderer);
        renderer = (RendererBase) myRenderer;
      } else {
        return null;
      }
    }
    return renderer;
  }


  private static Renderer getRendererInternal(
      final FacesContext facesContext, final String family, final String rendererType) {
    final RenderKitFactory rkFactory = (RenderKitFactory) FactoryFinder.getFactory(FactoryFinder.RENDER_KIT_FACTORY);
    final RenderKit renderKit = rkFactory.getRenderKit(facesContext, facesContext.getViewRoot().getRenderKitId());
    final Renderer myRenderer = renderKit.getRenderer(family, rendererType);
    return myRenderer;
  }

  public static Object findParameter(final UIComponent component, final String name) {
    for (final UIComponent child : component.getChildren()) {
      if (child instanceof UIParameter) {
        final UIParameter parameter = (UIParameter) child;
        if (LOG.isDebugEnabled()) {
          LOG.debug("Select name='" + parameter.getName() + "'");
          LOG.debug("Select value='" + parameter.getValue() + "'");
        }
        if (name.equals(parameter.getName())) {
          return parameter.getValue();
        }
      }
    }
    return null;
  }

  /**
   * <p>
   * The search depends on the number of prefixed colons in the relativeId:
   * </p>
   * <dl>
   * <dd>number of prefixed colons == 0</dd>
   * <dt>fully relative</dt>
   * <dd>number of prefixed colons == 1</dd>
   * <dt>absolute (still normal findComponent syntax)</dt>
   * <dd>number of prefixed colons == 2</dd>
   * <dt>search in the current naming container (same as 0 colons)</dt>
   * <dd>number of prefixed colons == 3</dd>
   * <dt>search in the parent naming container of the current naming container</dt>
   * <dd>number of prefixed colons &gt; 3</dd>
   * <dt>go to the next parent naming container for each additional colon</dt>
   * </dl>
   * <p>
   * If a literal is specified: to use more than one identifier the identifiers must be space delimited.
   * </p>
   */
  public static UIComponent findComponent(final UIComponent from, final String relativeId) {
    UIComponent from1 = from;
    String relativeId1 = relativeId;
    final int idLength = relativeId1.length();
    if (idLength > 0
        && relativeId1.charAt(0) == '@'
        && "@this".equals(relativeId1)) {
      return from1;
    }

    // Figure out how many colons
    int colonCount = 0;
    while (colonCount < idLength) {
      if (relativeId1.charAt(colonCount) != UINamingContainer.getSeparatorChar(FacesContext.getCurrentInstance())) {
        break;
      }
      colonCount++;
    }

    // colonCount == 0: fully relative
    // colonCount == 1: absolute (still normal findComponent syntax)
    // colonCount > 1: for each extra colon after 1, go up a naming container
    // (to the view root, if naming containers run out)
    if (colonCount > 1) {
      relativeId1 = relativeId1.substring(colonCount);
      for (int j = 1; j < colonCount; j++) {
        while (from1.getParent() != null) {
          from1 = from1.getParent();
          if (from1 instanceof NamingContainer) {
            break;
          }
        }
      }
    }
    return from1.findComponent(relativeId1);
  }

  /**
   * Resolves the real clientIds.
   */
  public static String evaluateClientIds(
      final FacesContext context, final UIComponent component, final String[] componentIds) {
    final List<String> result = new ArrayList<>(componentIds.length);
    for (final String id : componentIds) {
      if (!StringUtils.isBlank(id)) {
        final String clientId = evaluateClientId(context, component, id);
        if (clientId != null) {
          result.add(clientId);
        }
      }
    }
    if (result.isEmpty()) {
      return null;
    } else {
      return StringUtils.join(result, ' ');
    }
  }

  /**
   * Resolves the real clientId.
   */
  public static String evaluateClientId(
      final FacesContext context, final UIComponent component, final String componentId) {
    final UIComponent partiallyComponent = ComponentUtils.findComponent(component, componentId);
    if (partiallyComponent != null) {
      final String clientId = partiallyComponent.getClientId(context);
      if (partiallyComponent instanceof AbstractUISheet) {
        final int rowIndex = ((AbstractUISheet) partiallyComponent).getRowIndex();
        if (rowIndex >= 0 && clientId.endsWith(Integer.toString(rowIndex))) {
          return clientId.substring(0, clientId.lastIndexOf(UINamingContainer.getSeparatorChar(context)));
        }
      }
      return clientId;
    }
    LOG.error("No component found for id='{}', search base component is '{}'",
        componentId, component != null ? component.getClientId(context) : "<null>");
    return null;
  }

  public static String[] splitList(final String renderers) {
    return StringUtils.split(renderers, LIST_SEPARATOR_CHARS);
  }

  public static Object getConvertedValue(
      final FacesContext facesContext, final UIComponent component, final String stringValue) {
    try {
      final Renderer renderer = getRenderer(facesContext, component);
      if (renderer != null) {
        if (component instanceof UISelectMany) {
          final Object converted = renderer.getConvertedValue(facesContext, component, new String[]{stringValue});
          if (converted instanceof Object[]) {
            return ((Object[]) converted)[0];
          } else if (converted instanceof List) {
            return ((List) converted).get(0);
          } else if (converted instanceof Collection) {
            return ((Collection) converted).iterator().next();
          } else {
            return null;
          }
        } else {
          return renderer.getConvertedValue(facesContext, component, stringValue);
        }
      } else if (component instanceof ValueHolder) {
        Converter converter = ((ValueHolder) component).getConverter();
        if (converter == null) {
          //Try to find out by value expression
          final ValueExpression expression = component.getValueExpression("value");
          if (expression != null) {
            final Class valueType = expression.getType(facesContext.getELContext());
            if (valueType != null) {
              converter = facesContext.getApplication().createConverter(valueType);
            }
          }
        }
        if (converter != null) {
          converter.getAsObject(facesContext, component, stringValue);
        }
      }
    } catch (final Exception e) {
      LOG.warn("Can't convert string value '" + stringValue + "'", e);
    }
    return stringValue;
  }

  public static Markup markupOfSeverity(final FacesMessage.Severity maximumSeverity) {
    if (FacesMessage.SEVERITY_FATAL.equals(maximumSeverity)) {
      return Markup.FATAL;
    } else if (FacesMessage.SEVERITY_ERROR.equals(maximumSeverity)) {
      return Markup.ERROR;
    } else if (FacesMessage.SEVERITY_WARN.equals(maximumSeverity)) {
      return Markup.WARN;
    } else if (FacesMessage.SEVERITY_INFO.equals(maximumSeverity)) {
      return Markup.INFO;
    }
    return null;
  }

  public static FacesMessage.Severity getMaximumSeverityOfChildrenMessages(
      final FacesContext facesContext, final NamingContainer container) {
    if (container instanceof UIComponent) {
      final String clientId = ((UIComponent) container).getClientId(facesContext);
      FacesMessage.Severity max = null;
      for (final String id : (Iterable<String>) facesContext::getClientIdsWithMessages) {
        if (id != null && id.startsWith(clientId)) {
          final Iterator messages = facesContext.getMessages(id);
          while (messages.hasNext()) {
            final FacesMessage message = (FacesMessage) messages.next();
            if (max == null || message.getSeverity().getOrdinal() > max.getOrdinal()) {
              max = message.getSeverity();
            }
          }
        }
      }
      return max;
    }
    return null;
  }

  /**
   * Adding a data attribute to the component. The name must start with "data-", e. g. "data-tobago-foo" or "data-bar"
   */
  public static void putDataAttributeWithPrefix(
      final UIComponent component, final DataAttributes name, final Object value) {
    if (name.getValue().startsWith("data-")) {
      putDataAttribute(component, name.getValue().substring(5), value);
    } else {
      LOG.error("The name must start with 'data-' but it doesn't: '" + name + "'");
    }
  }

  /**
   * Adding a data attribute to the component. The name should not start with "data-", e. g. "tobago-foo" or "bar"
   */
  public static void putDataAttribute(final UIComponent component, final Object name, final Object value) {
    Map<Object, Object> map = getDataAttributes(component);
    if (map == null) {
      map = new HashMap<>();
      component.getAttributes().put(DATA_ATTRIBUTES_KEY, map);
    }
    if (map.containsKey(name)) {
      LOG.warn("Data attribute '{}' is already set for component '{}' (old value='{}', new value='{}')!",
          name, component.getClientId(), map.get(name), value);
    }
    map.put(name, value);
  }

  @SuppressWarnings("unchecked")
  public static Map<Object, Object> getDataAttributes(final UIComponent component) {
    return (Map<Object, Object>) component.getAttributes().get(DATA_ATTRIBUTES_KEY);
  }

  public static Object getDataAttribute(final UIComponent component, final String name) {
    final Map<Object, Object> map = getDataAttributes(component);
    return map != null ? map.get(name) : null;
  }

  /**
   * May return null, if no converter can be find.
   */
  public static Converter getConverter(
      final FacesContext facesContext, final UIComponent component, final Object value) {

    Converter converter = null;
    if (component instanceof ValueHolder) {
      converter = ((ValueHolder) component).getConverter();
    }

    if (converter == null) {
      final ValueExpression valueExpression = component.getValueExpression("value");
      if (valueExpression != null) {
        Class converterType = null;
        try {
          converterType = valueExpression.getType(facesContext.getELContext());
        } catch (final Exception e) {
          // ignore, seems not to be possible, when EL is a function like #{bean.getName(item.id)}
        }
        if (converterType == null) {
          if (value != null) {
            converterType = value.getClass();
          }
        }
        if (converterType != null && converterType != Object.class) {
          converter = facesContext.getApplication().createConverter(converterType);
        }
      }
    }

    return converter;
  }

  public static String getFormattedValue(
      final FacesContext facesContext, final UIComponent component, final Object currentValue)
      throws ConverterException {

    if (currentValue == null) {
      return "";
    }

    final Converter converter = ComponentUtils.getConverter(facesContext, component, currentValue);
    if (converter != null) {
      return converter.getAsString(facesContext, component, currentValue);
    } else {
      return currentValue.toString();
    }
  }

  public static UIComponent createComponent(
      final FacesContext facesContext, final String componentType, final RendererTypes rendererType,
      final String clientId) {
    final UIComponent component = facesContext.getApplication().createComponent(componentType);
    if (rendererType != null) {
      component.setRendererType(rendererType.name());
    }
    component.setId(clientId);
    return component;
  }

  public static List<UIComponent> findLayoutChildren(final UIComponent container) {
    final List<UIComponent> result = new ArrayList<>();
    addLayoutChildren(container, result);
    return result;
  }

  private static void addLayoutChildren(final UIComponent component, final List<UIComponent> result) {
    for (final UIComponent child : component.getChildren()) {
      if (child instanceof Visual && !((Visual) child).isPlain()
          || (UIComponent.isCompositeComponent(child) && !child.isRendered())) {
        result.add(child);
      } else {
        // Child seems to be transparent for layout, like UIForm with "plain" set.
        // So we try to add the inner components.
        addLayoutChildren(child, result);
      }
    }

    final UIComponent child = component.getFacet(UIComponent.COMPOSITE_FACET_NAME);
    if (child instanceof Visual && !((Visual) child).isPlain()) {
      result.add(child);
    } else if (child != null) {
      // Child seems to be transparent for layout, like UIForm with "plain" set.
      // So we try to add the inner components.
      addLayoutChildren(child, result);
    }
  }

  /**
   * returns the "confirmation" attribute or the value of the "confirmation" facet of a component.
   *
   * @since Tobago 4.4.0
   */
  public static String getConfirmation(final UIComponent component) {
    final String confirmation = getStringAttribute(component, Attributes.confirmation, null);
    if (confirmation != null) {
      return confirmation;
    }
    final UIComponent facet = ComponentUtils.getFacet(component, Facets.confirmation);
    if (facet instanceof ValueHolder && ((UIComponent) facet).isRendered()) {
      final ValueHolder valueHolder = (ValueHolder) facet;
      return "" + valueHolder.getValue();
    } else if (facet != null && !(facet instanceof ValueHolder)) {
      LOG.warn("The content of a confirmation facet must be a ValueHolder. Use e. g. <tc:out>.");
    }
    return null;
  }
}
