/*
 * 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 javax.faces.component;

import javax.faces.application.FacesMessage;
import javax.faces.context.FacesContext;
import javax.faces.convert.Converter;
import javax.faces.convert.ConverterException;
import javax.faces.el.EvaluationException;
import javax.faces.el.MethodBinding;
import javax.faces.el.ValueBinding;
import javax.faces.event.AbortProcessingException;
import javax.faces.event.FacesEvent;
import javax.faces.event.ValueChangeEvent;
import javax.faces.event.ValueChangeListener;
import javax.faces.render.Renderer;
import javax.faces.validator.Validator;
import javax.faces.FacesException;
import java.util.ArrayList;
import java.util.List;

/**
 * see Javadoc of <a href="http://java.sun.com/j2ee/javaserverfaces/1.1_01/docs/api/index.html">JSF Specification</a>
 *
 * @JSFComponent
 *   type = "javax.faces.Input"
 *   family = "javax.faces.Input"
 *   desc = "UIInput"
 *   
 * @author Manfred Geiler (latest modification by $Author$)
 * @version $Revision$ $Date$
 */
public class UIInput extends UIOutput implements EditableValueHolder
{
    public static final String COMPONENT_TYPE = "javax.faces.Input";
    public static final String COMPONENT_FAMILY = "javax.faces.Input";
    private static final String DEFAULT_RENDERER_TYPE = "javax.faces.Text";
    private static final boolean DEFAULT_IMMEDIATE = false;
    private static final boolean DEFAULT_REQUIRED = false;

    public static final String CONVERSION_MESSAGE_ID = "javax.faces.component.UIInput.CONVERSION";
    public static final String REQUIRED_MESSAGE_ID = "javax.faces.component.UIInput.REQUIRED";
    private static final String ERROR_HANDLING_EXCEPTION_LIST = "org.apache.myfaces.errorHandling.exceptionList";

    private static final Validator[] EMPTY_VALIDATOR_ARRAY = new Validator[0];

    private Boolean _immediate = null;
    private Boolean _required = null;

    private Object _submittedValue = null;
    private boolean _localValueSet = false;
    private boolean _valid = true;
    private MethodBinding _validator = null;
    private MethodBinding _valueChangeListener = null;
    private List _validatorList = null;

    // use javadoc inherited from EditableValueHolder
    /**
     * @JSFProperty
     *   tagExcluded = "true"
     */
    public Object getSubmittedValue()
    {
        return _submittedValue;
    }

    // use javadoc inherited from EditableValueHolder
    public void setSubmittedValue(Object submittedValue)
    {
        _submittedValue = submittedValue;
    }

    /**
     * Store the specified object as the "local value" of this component.
     * The value-binding named "value" (if any) is ignored; the object is
     * only stored locally on this component. During the "update model"
     * phase, if there is a value-binding named "value" then this local
     * value will be stored via that value-binding and the "local value"
     * reset to null.
     */
    public void setValue(Object value)
    {
        setLocalValueSet(true);
        super.setValue(value);
    }

    /**
     * Return the current value of this component.
     * <p>
     * If a submitted value has been converted but not yet pushed into the
     * model, then return that locally-cached value (see isLocalValueSet).
     * <p>
     * Otherwise, evaluate an EL expression to fetch a value from the model. 
     */
    public Object getValue()
    {
        if (isLocalValueSet()) return super.getLocalValue();
        return super.getValue();
    }

    // use javadoc inherited from EditableValueHolder
    /**
     * @JSFProperty
     *   tagExcluded = "true"
     */
    public boolean isLocalValueSet()
    {
        return _localValueSet;
    }

    // use javadoc inherited from EditableValueHolder
    public void setLocalValueSet(boolean localValueSet)
    {
        _localValueSet = localValueSet;
    }

    // use javadoc inherited from EditableValueHolder
    /**
     * @JSFProperty
     *   tagExcluded = "true"
     */
    public boolean isValid()
    {
        return _valid;
    }

    // use javadoc inherited from EditableValueHolder
    public void setValid(boolean valid)
    {
        _valid = valid;
    }

    // use javadoc inherited from EditableValueHolder    
    /**
     * A method binding EL expression, accepting FacesContext, UIComponent,
     * and Object parameters, and returning void, that validates the
     * component's local value.
     * 
     * @JSFProperty
     *   stateHolder="true"
     *   returnSignature="void"
     *   methodSignature="javax.faces.context.FacesContext,javax.faces.component.UIComponent,java.lang.Object"
     */
    public MethodBinding getValidator()
    {
        return _validator;
    }

    // use javadoc inherited from EditableValueHolder
    public void setValidator(MethodBinding validator)
    {
        _validator = validator;
    }

    // use javadoc inherited from EditableValueHolder
    /**
     * A method binding EL expression, accepting a ValueChangeEvent parameter
     * and returning void. The specified method is invoked if this component
     * is modified. The phase that this handler is fired in can be controlled
     * via the immediate attribute.
     * 
     * @JSFProperty
     *   stateHolder="true"
     *   returnSignature="void"
     *   methodSignature="javax.faces.event.ValueChangeEvent"
     */
    public MethodBinding getValueChangeListener()
    {
        return _valueChangeListener;
    }

    // use javadoc inherited from EditableValueHolder
    public void setValueChangeListener(MethodBinding valueChangeListener)
    {
        _valueChangeListener = valueChangeListener;
    }

    /**
     * Set the "submitted value" of this component from the relevant data
     * in the current servlet request object.
     * <p>
     * If this component is not rendered, then do nothing; no output would
     * have been sent to the client so no input is expected.
     * <p>
     * Invoke the inherited functionality, which typically invokes the
     * renderer associated with this component to extract and set this
     * component's "submitted value".
     * <p>
     * If this component is marked "immediate", then immediately apply
     * validation to the submitted value found. On error, call context
     * method "renderResponse" which will force processing to leap to
     * the "render response" phase as soon as the "decode" step has
     * completed for all other components.
     */
    public void processDecodes(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        try
        {
            setCachedFacesContext(context);
            if (!isRendered())
            {
                return;
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
        super.processDecodes(context);
        try
        {
            setCachedFacesContext(context);
            if (isImmediate())
            {
                try
                {
                    validate(context);
                }
                catch (RuntimeException e)
                {
                    context.renderResponse();
                    throw e;
                }
                if (!isValid())
                {
                    context.renderResponse();
                }
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }

    public void processValidators(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        try
        {
            setCachedFacesContext(context);
            if (!isRendered())
            {
                return;
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
        
        super.processValidators(context);

        try
        {
            setCachedFacesContext(context);
            if (!isImmediate())
            {
                try
                {
                    validate(context);
                }
                catch (RuntimeException e)
                {
                    context.renderResponse();
                    throw e;
                }
                if (!isValid())
                {
                    context.renderResponse();
                }
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }

    public void processUpdates(FacesContext context)
    {
        if (context == null)
        {
            throw new NullPointerException("context");
        }
        try
        {
            setCachedFacesContext(context);
            if (!isRendered())
            {
                return;
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
        super.processUpdates(context);

        try
        {
            setCachedFacesContext(context);
            try
            {
                updateModel(context);
            }
            catch (RuntimeException e)
            {
                context.renderResponse();
                throw e;
            }
            if (!isValid())
            {
                context.renderResponse();
            }
        }
        finally
        {
            setCachedFacesContext(null);
        }
    }

    public void decode(FacesContext context)
    {
        //We (re)set to valid, so that component automatically gets (re)validated
        setValid(true);
        super.decode(context);
    }

    public void broadcast(FacesEvent event)
            throws AbortProcessingException
    {
        // invoke standard listeners attached to this component first
        super.broadcast(event);

        //Check if the event is applicable for ValueChangeListener
        if (event instanceof ValueChangeEvent){
            // invoke the single listener defined directly on the component
            MethodBinding valueChangeListenerBinding = getValueChangeListener();
            if (valueChangeListenerBinding != null)
            {
                try
                {
                    valueChangeListenerBinding.invoke(getFacesContext(),
                                                      new Object[]{event});
                }
                catch (EvaluationException e)
                {
                    Throwable cause = e.getCause();
                    if (cause != null && cause instanceof AbortProcessingException)
                    {
                        throw (AbortProcessingException)cause;
                    }
                    else
                    {
                        throw e;
                    }
                }
            }
        }
    }

    public void updateModel(FacesContext context)
    {
        if (!isValid()) return;
        if (!isLocalValueSet()) return;
        ValueBinding vb = getValueBinding("value");
        if (vb == null) return;
        try
        {
            vb.setValue(context, getLocalValue());
            setValue(null);
            setLocalValueSet(false);
        }
         catch (Exception e)
        {
            //Object[] args = {getId()};
            context.getExternalContext().log(e.getMessage(), e);
            _MessageUtils.addErrorMessage(context, this,CONVERSION_MESSAGE_ID,new Object[]{getId()});
            setValid(false);

            /* we are not allowed to throw exceptions here - we still need the full stack-trace later on
             * to process it later in our error-handler
             */
            queueExceptionInRequest(context, vb, e);
        }
    }

    /**
     * For development and production, we want to offer a single point
     * to which error-handlers can attach. So we queue up all ocurring
     * exceptions and later pass them to the configured error-handler.
     */
    private void queueExceptionInRequest(FacesContext context, ValueBinding binding, Exception e) {
        List li = (List) context.getExternalContext().getRequestMap().get(ERROR_HANDLING_EXCEPTION_LIST);
        if(null==li) {
            li = new ArrayList();
            context.getExternalContext().getRequestMap().put(ERROR_HANDLING_EXCEPTION_LIST, li);
        }
        li.add(new FacesException("Exception while setting value for expression : "+
            binding.getExpressionString()+" of component with path : "
            + _ComponentUtils.getPathToComponent(this),e));
    }

    protected void validateValue(FacesContext context,Object convertedValue)
    {
        boolean empty = convertedValue == null ||
                        (convertedValue instanceof String
                         && ((String)convertedValue).length() == 0);

        if (isRequired() && empty)
        {
            _MessageUtils.addErrorMessage(context, this, REQUIRED_MESSAGE_ID,new Object[]{getId()});
            setValid(false);
            return;
        }

        if (!empty)
        {
            _ComponentUtils.callValidators(context, this, convertedValue);
        }

    }

    /**
     * Determine whether the new value is valid, and queue a ValueChangeEvent
     * if necessary.
     * <p>
     * The "submitted value" is converted to the necessary type; conversion
     * failure is reported as an error and validation processing terminates
     * for this component. See documentation for method getConvertedValue
     * for details on the conversion process.
     * <p>
     * Any validators attached to this component are then run, passing
     * the converted value.
     * <p>
     * The old value of this component is then fetched (possibly involving
     * the evaluation of a value-binding expression, ie invoking a method
     * on a user object). The old value is compared to the new validated
     * value, and if they are different then a ValueChangeEvent is queued
     * for later processing.
     * <p>
     * On successful completion of this method:
     * <ul>
     * <li> isValid() is true
     * <li> isLocalValueSet() is true
     * <li> getValue() will return the converted value, NOT evaluate the
     * EL expression bound to the "value" attribute. Note that the getValue
     * method will return to normal behaviour (evaluating its EL expression)
     * after a successful update-model phase, ie after pushing this converted
     * value into the model.
     * <li> submittedValue is reset to null
     * <li> a ValueChangeEvent is queued if the new value != old value
     * </ul> 
     * 
     */
    public void validate(FacesContext context)
    {
        if (context == null) throw new NullPointerException("context");

        try {

            Object submittedValue = getSubmittedValue();
            if (submittedValue == null) return;

            Object convertedValue = getConvertedValue(context, submittedValue);

            if (!isValid()) return;

            validateValue(context, convertedValue);

            if (!isValid()) return;

            Object previousValue = getValue();
            setValue(convertedValue);
            setSubmittedValue(null);
            if (compareValues(previousValue, convertedValue))
            {
                queueEvent(new ValueChangeEvent(this, previousValue, convertedValue));
            }
        }
        catch (Exception ex)
        {
            throw new FacesException("Exception while validating component with path : "+_ComponentUtils.getPathToComponent(this),ex);
        }
    }

    /**
     * Convert the provided object to the desired value.
     * <p>
     * If there is a renderer for this component, then call the renderer's
     * getConvertedValue method. While this can of course be implemented in
     * any way the renderer desires, it typically performs exactly the same
     * processing that this method would have done anyway (ie that described
     * below for the no-renderer case).
     * <p>
     * Otherwise:
     * <ul>
     * <li>If the submittedValue is not a String then just return the
     *   submittedValue unconverted.
     * <li>If there is no "value" value-binding then just return the
     *   submittedValue unconverted.
     * <li>Use introspection to determine the type of the target 
     *   property specified by the value-binding, and then use
     *   Application.createConverter to find a converter that can
     *   map from String to the required type. Apply the converter
     *   to the submittedValue and return the result. 
     * </ul>
     */
    protected Object getConvertedValue(FacesContext context, Object submittedValue)
    {
        try
        {
            Renderer renderer = getRenderer(context);
            if (renderer != null)
            {
                return renderer.getConvertedValue(context, this, submittedValue);
            }
            else if (submittedValue instanceof String)
            {
                Converter converter = _SharedRendererUtils.findUIOutputConverter(context, this);
                if (converter != null)
                {
                    return converter.getAsObject(context, this, (String)submittedValue);
                }
            }
        }
        catch (ConverterException e)
        {
            FacesMessage facesMessage = e.getFacesMessage();
            if (facesMessage != null)
            {
                context.addMessage(getClientId(context), facesMessage);
            }
            else
            {
                _MessageUtils.addErrorMessage(context, this, CONVERSION_MESSAGE_ID,new Object[]{getId()});
            }
            setValid(false);
        }
        return submittedValue;
    }



    protected boolean compareValues(Object previous,
                                      Object value)
    {
        return previous==null?(value!=null):(!previous.equals(value));
    }

    public void addValidator(Validator validator)
    {
        if (validator == null) throw new NullPointerException("validator");
        if (_validatorList == null)
        {
            _validatorList = new ArrayList();
        }
        _validatorList.add(validator);
    }

    public Validator[] getValidators()
    {
        return _validatorList != null ?
               (Validator[])_validatorList.toArray(new Validator[_validatorList.size()]) :
               EMPTY_VALIDATOR_ARRAY;
    }

    public void removeValidator(Validator validator)
    {
        if (validator == null) throw new NullPointerException("validator");
        if (_validatorList != null)
        {
            _validatorList.remove(validator);
        }
    }

    public void addValueChangeListener(ValueChangeListener listener)
    {
        addFacesListener(listener);
    }

    public ValueChangeListener[] getValueChangeListeners()
    {
        return (ValueChangeListener[])getFacesListeners(ValueChangeListener.class);
    }

    public void removeValueChangeListener(ValueChangeListener listener)
    {
        removeFacesListener(listener);
    }

    public Object saveState(FacesContext context)
    {
        Object values[] = new Object[9];
        values[0] = super.saveState(context);
        values[1] = _immediate;
        values[2] = Boolean.valueOf(_localValueSet);
        values[3] = _required;
        values[4] = _submittedValue;
        values[5] = Boolean.valueOf(_valid);
        values[6] = saveAttachedState(context, _validator);
        values[7] = saveAttachedState(context, _valueChangeListener);
        values[8] = saveAttachedState(context, _validatorList);
        return values;
    }

    public void restoreState(FacesContext context, Object state)
    {
        Object values[] = (Object[])state;
        super.restoreState(context, values[0]);
        _immediate = (Boolean)values[1];
        _localValueSet = ((Boolean)values[2]).booleanValue();
        _required = (Boolean)values[3];
        _submittedValue = values[4];
        _valid = ((Boolean)values[5]).booleanValue();
        _validator = (MethodBinding)restoreAttachedState(context, values[6]);
        _valueChangeListener = (MethodBinding)restoreAttachedState(context, values[7]);
        _validatorList = (List)restoreAttachedState(context, values[8]);

    }

    public UIInput()
    {
        setRendererType(DEFAULT_RENDERER_TYPE);
    }

    public String getFamily()
    {
        return COMPONENT_FAMILY;
    }

    public void setImmediate(boolean immediate)
    {
        _immediate = Boolean.valueOf(immediate);
    }

    /**
     * A boolean value that identifies the phase during which value change
     * events should fire. During normal event processing, value change
     * events are fired during the "process validations" phase of request
     * processing. If this attribute is set to "true", these methods are
     * fired instead at the end of the "apply request values" phase.
     * 
     * @JSFProperty
     */
    public boolean isImmediate()
    {
        if (_immediate != null) return _immediate.booleanValue();
        ValueBinding vb = getValueBinding("immediate");
        Boolean v = vb != null ? (Boolean)vb.getValue(getFacesContext()) : null;
        return v != null ? v.booleanValue() : DEFAULT_IMMEDIATE;
    }

    public void setRequired(boolean required)
    {
        _required = Boolean.valueOf(required);
    }

    /**
     * A boolean value that indicates whether an input value is required.
     * If this value is true, and no input value is provided, the error
     * message javax.faces.component.UIInput.REQUIRED is posted.
     * 
     * @JSFProperty
     */
    public boolean isRequired()
    {
        if (_required != null) return _required.booleanValue();
        ValueBinding vb = getValueBinding("required");
        Boolean v = vb != null ? (Boolean)vb.getValue(getFacesContext()) : null;
        return v != null ? v.booleanValue() : DEFAULT_REQUIRED;
    }
}
