/*
 * 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.empire.jsf2.components;

import java.io.IOException;
import java.util.Locale;
import java.util.Map;

import javax.el.ValueExpression;
import javax.faces.component.NamingContainer;
import javax.faces.component.UIInput;
import javax.faces.component.html.HtmlSelectOneMenu;
import javax.faces.component.visit.VisitCallback;
import javax.faces.component.visit.VisitContext;
import javax.faces.context.FacesContext;

import org.apache.empire.commons.ObjectUtils;
import org.apache.empire.commons.Options;
import org.apache.empire.commons.StringUtils;
import org.apache.empire.data.Column;
import org.apache.empire.exceptions.InvalidPropertyException;
import org.apache.empire.exceptions.NotSupportedException;
import org.apache.empire.jsf2.app.FacesUtils;
import org.apache.empire.jsf2.app.TextResolver;
import org.apache.empire.jsf2.controls.InputAttachedObjectsHandler;
import org.apache.empire.jsf2.controls.InputControl;
import org.apache.empire.jsf2.controls.InputControl.DisabledType;
import org.apache.empire.jsf2.controls.InputControl.InputInfo;
import org.apache.empire.jsf2.controls.InputControlManager;
import org.apache.empire.jsf2.controls.SelectInputControl;
import org.apache.empire.jsf2.utils.TagEncodingHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class SelectTag extends UIInput implements NamingContainer
{
    // Logger
    private static final Logger log = LoggerFactory.getLogger(SelectTag.class);
    
    public static final String SELECT_COMPONENT_ID = "select";

    protected SelectInputControl control = null;
    
    private class SelectInputInfo implements InputInfo
    {
        @Override
        public Column getColumn()
        {
            return null;
        }

        @Override
        public Options getOptions()
        {
            return SelectTag.this.getOptionList();
        }

        @Override
        public Object getValue(boolean evalExpression)
        {
            Object value = SelectTag.this.getValue();
            if (value != null)
            {
                if (value instanceof Enum<?>)
                    value = ((Enum<?>)value).name();
                else
                    value = String.valueOf(value);
            }
            return value;
        }

        @Override
        public String getFormat()
        {
            String nullText = SelectTag.this.getNullText();
            if (StringUtils.isEmpty(nullText))
                return null;
            // return format for null text
            return InputControl.FORMAT_NULL+nullText;
        }

        @Override
        public Locale getLocale()
        {
            return null;
        }

        @Override
        public String getText(String key)
        {
            return null;
        }

        @Override
        public TextResolver getTextResolver()
        {
            return  FacesUtils.getTextResolver(FacesContext.getCurrentInstance());
        }

        @Override
        public String getStyleClass(String addlStyle)
        {
            return null;
        }

        @Override
        public boolean isInsideUIData()
        {
            return false;
        }

        @Override
        public void setValue(Object value)
        {
            throw new NotSupportedException(SelectTag.this, "setValue");
        }

        @Override
        public void validate(Object value)
        {
        }

        @Override
        public boolean isRequired()
        {
            return !(SelectTag.this.isAllowNull());
        }

        @Override
        public boolean isModified()
        {
            Object modified = SelectTag.this.getAttributes().get("modified");
            return (modified!=null ? ObjectUtils.getBoolean(modified) : false);
        }

        @Override
        public boolean isDisabled()
        {
            return SelectTag.this.isDisabled();
        }

        @Override
        public DisabledType getDisabled()
        {
            return (SelectTag.this.isDisabled() ? DisabledType.DISABLED : DisabledType.NO);
        }

        @Override
        public String getInputId()
        {
            return "select";
        }

        @Override
        public boolean hasError()
        {
            return false;
        }

        @Override
        public Object getAttribute(String name)
        {
            return null;
        }

        @Override
        public Object getAttributeEx(String name)
        {
            Object value = SelectTag.this.getAttributes().get(name);
            if (value==null)
            {   // try value expression
                ValueExpression ve = SelectTag.this.getValueExpression(name);
                if (ve!=null)
                {   // It's a value expression
                    FacesContext ctx = FacesContext.getCurrentInstance();
                    value = ve.getValue(ctx.getELContext());
                }
            }
            return value;
        }
        
    }
    
    private SelectInputInfo selectInputInfo = new SelectInputInfo();
    
    public SelectTag()
    {
        log.trace("component select created");
    }

    @Override
    public String getFamily()
    {
        return "javax.faces.NamingContainer";
    }
    
    /**
     * remember original clientId
     * necessary only inside UIData
     */
    private String treeClientId = null;
    
    @Override
    public boolean visitTree(VisitContext visitContext, VisitCallback callback) 
    {
        FacesContext context = visitContext.getFacesContext();
        treeClientId = getClientId(context);
        return super.visitTree(visitContext, callback);
    }

    @Override
    public String getClientId(FacesContext context)
    {
        // Check if dynamic components are being created
        if (this.treeClientId!=null && control!=null && control.isCreatingComponents())
        {   // return the original tree client id
            return treeClientId; 
        }
        // default behavior
        return super.getClientId(context);
    }

    @Override
    public void encodeBegin(FacesContext context)
        throws IOException
    {
        // add label and input components when the view is loaded for the first time
        UIInput inputComponent = null;
        TextResolver textResolver = FacesUtils.getTextResolver(context);
        if (getChildCount() > 0)
        {
            inputComponent = getInputComponent();
            if (inputComponent instanceof HtmlSelectOneMenu)
            {
                this.control = (SelectInputControl) InputControlManager.getControl(SelectInputControl.NAME);
                // disabled
                boolean disabled = isDisabled();
                ((HtmlSelectOneMenu) inputComponent).setDisabled(disabled);
                // Options (sync)
                control.syncOptions((HtmlSelectOneMenu) inputComponent, textResolver, selectInputInfo);
                setInputValue((HtmlSelectOneMenu) inputComponent);
            }
            else
            { // Something's wrong here?
                log.warn("WARN: Unexpected child node for {}! Child item type is {}.", getClass().getName(), inputComponent.getClass().getName());
                inputComponent = null;
            }
        }
        if (inputComponent == null)
        {
            inputComponent = createSelectOneMenu(textResolver);
            this.getChildren().add(0, inputComponent);
            // attach objects
            addAttachedObjects(context, inputComponent);
        }
        else
        {   // update attached objects
            updateAttachedObjects(context, inputComponent);
        }
        // render components
        inputComponent.encodeAll(context);
        // default
        super.encodeBegin(context);
    }

    @Override
    public void updateModel(FacesContext context)
    {
        // check read only
        if (!isDisabled())
        {
            UIInput inputComponent = getInputComponent();

            Object value = (inputComponent==null ? "" : inputComponent.getValue());
            if (value == null)
                value = "";
            setValue(value);
        }
        super.updateModel(context);
    }

    @Override
    public void validate(FacesContext context)
    {
        // nothing submitted (AJAX part request, e.g. calendar component) or readonly (won't be set
        // in updateModel())?
        UIInput inputComponent = getInputComponent();
        if (inputComponent == null)
        {
            return;
        }
        // component itself already checked validity, was it successful?
        if (!inputComponent.isValid() || isDisabled())
        {
            return;
        }
        // nothing to do
        super.validate(context);
    }

    protected UIInput getInputComponent()
    {
        if (getChildren().size() == 0)
        {
            return null;
        }

        return (UIInput) getChildren().get(0);
    }

    protected Options getOptionList()
    {
        Object options = getAttributes().get("options");
        if (!(options instanceof Options))
        {
            return new Options();
        }
        return ((Options) options);
    }

    protected boolean isAllowNull()
    {
        Object allowNull = getAttributes().get("allowNull");
        return ObjectUtils.getBoolean(allowNull);
    }

    protected String getNullText()
    {
        Object nullText = getAttributes().get("nullText");
        return StringUtils.toString(nullText, "");
    }

    protected String getInputControl()
    {
        Object inputControl = getAttributes().get("inputControl");
        return StringUtils.toString(inputControl, SelectInputControl.NAME);
    }

    protected boolean isDisabled()
    {
        Object disabled = getAttributes().get("disabled");
        return ObjectUtils.getBoolean(disabled);
    }

    protected UIInput createSelectOneMenu(TextResolver textResolver)
    {
        // find inputControl by name
        InputControl inputControl = InputControlManager.getControl(getInputControl());
        if (inputControl==null || !(inputControl instanceof SelectInputControl))
            throw new InvalidPropertyException("inputControl", getInputControl());
        // create component
        this.control = (SelectInputControl)inputControl; 
        HtmlSelectOneMenu input = control.createMenuComponent(this);
        // css style
        String userStyle = StringUtils.toString(getAttributes().get("styleClass"));
        String cssStyle = TagEncodingHelper.assembleStyleClassString("eSelect", null, null, userStyle);
        input.setStyleClass(cssStyle);
        // other attributes
        copyAttributes(input);
        input.setId(SELECT_COMPONENT_ID);
        // Options
        control.initOptions(input, textResolver, selectInputInfo);
        // disabled
        boolean disabled = isDisabled();
        input.setDisabled(disabled);
        control.addRemoveDisabledStyle(input, disabled);
        // input.setLabel(getLabelString());
        // input.setRequired(col.isRequired() && !col.isAutoGenerated());
        // input.setId(this.getId() + INPUT_SUFFIX);
        setInputValue(input);
        return input;
    }

    protected void setInputValue(HtmlSelectOneMenu input)
    {
        Object value = getValue();
        if (value != null)
        {
            if (value instanceof Enum<?>)
                value = ((Enum<?>)value).name();
            else
                value = String.valueOf(value);
        }
        input.setValue(value);
    }

    protected void copyAttributes(HtmlSelectOneMenu input)
    {
        // set id
        String inputId = this.getId();
        if (StringUtils.isNotEmpty(inputId))
        { // remove trailing underscore (workaround since parent and child may not have the same name)
            if (inputId.endsWith("_"))
            {
                inputId = inputId.substring(0, inputId.length() - 1);
            }
            input.setId(inputId);
        }

        Map<String, Object> attr = getAttributes();
        Object value;
        if ((value = attr.get("style")) != null)
        {
            input.setStyle(StringUtils.toString(value));
        }
        if ((value = attr.get("tabindex")) != null)
        {
            input.setTabindex(StringUtils.toString(value));
        }
        if ((value = attr.get("onchange")) != null)
        {
            input.setOnchange(StringUtils.toString(value));
        }
    }
    
    protected void addAttachedObjects(FacesContext context, UIInput inputComponent)
    {
        InputAttachedObjectsHandler aoh = InputControlManager.getAttachedObjectsHandler();
        if (aoh!=null)
            aoh.addAttachedObjects(this, context, null, inputComponent);
    }
    
    protected void updateAttachedObjects(FacesContext context, UIInput inputComponent)
    {
        InputAttachedObjectsHandler aoh = InputControlManager.getAttachedObjectsHandler();
        if (aoh!=null)
            aoh.updateAttachedObjects(this, context, null, inputComponent);
    }
}
