/*
 * 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.Facets;
import org.apache.myfaces.tobago.component.RendererTypes;
import org.apache.myfaces.tobago.internal.component.AbstractUIButton;
import org.apache.myfaces.tobago.internal.component.AbstractUIInput;
import org.apache.myfaces.tobago.internal.component.AbstractUIOut;
import org.apache.myfaces.tobago.internal.component.AbstractUISelectOneChoice;
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.internal.util.StringUtils;
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.HtmlAttributes;
import org.apache.myfaces.tobago.renderkit.html.HtmlElements;
import org.apache.myfaces.tobago.renderkit.html.HtmlInputTypes;
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.context.FacesContext;
import javax.faces.validator.LengthValidator;
import javax.faces.validator.RegexValidator;
import javax.faces.validator.Validator;
import java.io.IOException;
import java.lang.invoke.MethodHandles;

public class InRenderer extends MessageLayoutRendererBase {

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

  @Override
  public HtmlElements getComponentTag() {
    return HtmlElements.TOBAGO_IN;
  }

  @Override
  protected void encodeBeginField(final FacesContext facesContext, final UIComponent component)
      throws IOException {
    final AbstractUIInput input = (AbstractUIInput) component;
    final String title = HtmlRendererUtils.getTitleFromTipAndMessages(facesContext, input);
    final String currentValue = getCurrentValue(facesContext, input);
    final boolean password = ComponentUtils.getBooleanAttribute(input, Attributes.password);
    if (LOG.isDebugEnabled()) {
      LOG.debug("currentValue = '{}'", StringUtils.toConfidentialString(currentValue, password));
    }
    final HtmlInputTypes type = password ? HtmlInputTypes.PASSWORD : HtmlInputTypes.TEXT;
    final String clientId = input.getClientId(facesContext);
    final String fieldId = input.getFieldId(facesContext);
    final boolean readonly = input.isReadonly();
    final boolean disabled = input.isDisabled();
    final boolean required = ComponentUtils.getBooleanAttribute(input, Attributes.required);

    final TobagoResponseWriter writer = getResponseWriter(facesContext);

    final UIComponent after = ComponentUtils.getFacet(input, Facets.after);
    final UIComponent before = ComponentUtils.getFacet(input, Facets.before);

    if (after != null || before != null) {
      writer.startElement(HtmlElements.DIV); // Wrapping the field to fix input groups with flexLeft/flexRight
      writer.writeClassAttribute(TobagoClass.INPUT__GROUP__OUTER);
      writer.startElement(HtmlElements.DIV);
      writer.writeClassAttribute(BootstrapClass.INPUT_GROUP);
    }
    encodeGroupAddon(facesContext, writer, before, false);

    writer.startElement(HtmlElements.INPUT);

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

    writer.writeAttribute(HtmlAttributes.TYPE, type);
    writer.writeNameAttribute(clientId);
    writer.writeIdAttribute(fieldId);
    HtmlRendererUtils.writeDataAttributes(facesContext, writer, input);
    if (currentValue != null && !password) {
      writer.writeAttribute(HtmlAttributes.VALUE, currentValue, true);
    }
    if (title != null) {
      writer.writeAttribute(HtmlAttributes.TITLE, title, true);
    }
    int maxLength = 0;
    int minLength = 0;
    String pattern = null;
    for (final Validator validator : input.getValidators()) {
      if (validator instanceof LengthValidator) {
        final LengthValidator lengthValidator = (LengthValidator) validator;
        maxLength = lengthValidator.getMaximum();
        minLength = lengthValidator.getMinimum();
      } else if (validator instanceof RegexValidator) {
        final RegexValidator regexValidator = (RegexValidator) validator;
        pattern = regexValidator.getPattern();
      }
    }
    if (maxLength > 0) {
      writer.writeAttribute(HtmlAttributes.MAXLENGTH, maxLength);
    }
    if (minLength > 0) {
      writer.writeAttribute(HtmlAttributes.MINLENGTH, minLength);
    }
    if (pattern != null) {
      writer.writeAttribute(HtmlAttributes.PATTERN, pattern, true);
    }
    writer.writeAttribute(HtmlAttributes.READONLY, readonly);
    writer.writeAttribute(HtmlAttributes.DISABLED, disabled);
    writer.writeAttribute(HtmlAttributes.TABINDEX, input.getTabIndex());
    if (!disabled && !readonly) {
      writer.writeAttribute(HtmlAttributes.PLACEHOLDER, input.getPlaceholder(), true);
    }

    final CssItem rendererCssClass = getRendererCssClass();
    writer.writeClassAttribute(
        rendererCssClass,
//        rendererCssClass != null ? rendererCssClass.createMarkup(markup) : null,
        BootstrapClass.borderColor(ComponentUtils.getMaximumSeverity(input)),
        BootstrapClass.FORM_CONTROL,
        input.getCustomClass());

    writer.writeAttribute(HtmlAttributes.REQUIRED, required);
    HtmlRendererUtils.renderFocus(clientId, input.isFocus(), ComponentUtils.isError(input), facesContext, writer);
    writeAdditionalAttributes(facesContext, writer, input);

    writer.endElement(HtmlElements.INPUT);

    encodeBehavior(writer, facesContext, input);

    encodeGroupAddon(facesContext, writer, after, true);

    if (after != null || before != null) {
      writer.endElement(HtmlElements.DIV);
      writer.endElement(HtmlElements.DIV);
    }
  }

  private void encodeGroupAddon(
      final FacesContext facesContext, final TobagoResponseWriter writer, final UIComponent addon,
      final boolean isAfterFacet) throws IOException {
    if (addon != null) {
      for (final UIComponent child : RenderUtils.getFacetChildren(addon)) {
        if (child instanceof AbstractUIButton && ((AbstractUIButton) child).isParentOfCommands()) {
          if (isAfterFacet) {
            child.setRendererType(RendererTypes.ButtonInsideInAfter.name());
          } else {
            child.setRendererType(RendererTypes.ButtonInsideIn.name());
          }
          child.encodeAll(facesContext);
        } else {
          writer.startElement(HtmlElements.DIV);
          writer.writeClassAttribute(isAfterFacet
              ? BootstrapClass.INPUT_GROUP_APPEND : BootstrapClass.INPUT_GROUP_PREPEND);

          if (child instanceof AbstractUIButton) {
            child.encodeAll(facesContext);
          } else if (child instanceof AbstractUIOut) {
            child.setRendererType(RendererTypes.OutInsideIn.name());
            child.encodeAll(facesContext);
          } else if (child instanceof AbstractUISelectOneChoice) {
            child.setRendererType(RendererTypes.SelectOneChoiceInsideIn.name());
            child.encodeAll(facesContext);
          } else {
            writer.startElement(HtmlElements.SPAN);
            writer.writeClassAttribute(BootstrapClass.INPUT_GROUP_TEXT);
            child.encodeAll(facesContext);
            writer.endElement(HtmlElements.SPAN);
          }

          writer.endElement(HtmlElements.DIV);
        }
      }
    }
  }

  @Override
  protected void encodeEndField(final FacesContext facesContext, final UIComponent component) throws IOException {
  }

  protected CssItem getRendererCssClass() {
    return TobagoClass.IN;
  }

  protected void writeAdditionalAttributes(
      final FacesContext facesContext, final TobagoResponseWriter writer, final AbstractUIInput input)
      throws IOException {
  }

  @Override
  protected String getFieldId(final FacesContext facesContext, final UIComponent component) {
    final AbstractUIInput input = (AbstractUIInput) component;
    return input.getFieldId(facesContext);
  }
}
