/*
 * 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.sling.servlets.post.impl.helper;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jcr.PropertyType;

import org.apache.jackrabbit.JcrConstants;
import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.PersistenceException;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.SlingPostConstants;
import org.apache.sling.servlets.post.exceptions.PreconditionViolatedPersistenceException;

/**
 * Sets a property on the given resource, in some cases with a specific type and
 * value. For example, "lastModified" with an empty value is stored as the
 * current Date.
 * Special handling might apply if the resource is backed by a JCR node.
 */
public class SlingPropertyValueHandler {

    /**
     * Defines a map of auto properties
     */
    private static final Map<String, AutoType> AUTO_PROPS = new HashMap<>();
    static {
        AUTO_PROPS.put("created", AutoType.CREATED);
        AUTO_PROPS.put("createdBy", AutoType.CREATED_BY);
        AUTO_PROPS.put(JcrConstants.JCR_CREATED, AutoType.CREATED);
        AUTO_PROPS.put("jcr:createdBy", AutoType.CREATED_BY);
        AUTO_PROPS.put("lastModified", AutoType.MODIFIED);
        AUTO_PROPS.put("lastModifiedBy", AutoType.MODIFIED_BY);
        AUTO_PROPS.put(JcrConstants.JCR_LASTMODIFIED, AutoType.MODIFIED);
        AUTO_PROPS.put("jcr:lastModifiedBy", AutoType.MODIFIED_BY);
    }

    /**
     * the post processor
     */
    private final List<Modification> changes;

    private final DateParser dateParser;

    private final JCRSupport jcrSupport;

    /**
     * current date for all properties in this request
     */
    private final Calendar now = Calendar.getInstance();

    /**
     * Constructs a property value handler
     * @param dateParser the dateParser
     * @param jcrSupport the jcrSupport
     * @param changes the changes 
     */
    public SlingPropertyValueHandler(final DateParser dateParser,
            final JCRSupport jcrSupport,
            final List<Modification> changes) {
        this.dateParser = dateParser;
        this.jcrSupport = jcrSupport;
        this.changes = changes;
    }

    /** Return the AutoType for a given property name
     *  @return null if not found
     * */
    static AutoType getAutoType(String propertyName) {
        return AUTO_PROPS.get(propertyName);
    }

    /**
     * Set property on given node, with some automatic values when user provides
     * the field name but no value.
     *
     * html example for testing:
     * {@code
     *   <input type="hidden" name="created"/>
     *   <input type="hidden" name="lastModified"/>
     *   <input type="hidden" name="createdBy" />
     *   <input type="hidden" name="lastModifiedBy"/>
     * }
     *
     * @param parent the parent node
     * @param prop the request property
     * @throws PersistenceException if a resource error occurs
     */
    public void setProperty(final Resource parent, final RequestProperty prop)
    throws PersistenceException {
        final Modifiable mod = new Modifiable();
        mod.resource = parent;
        mod.node = jcrSupport.getNode(parent);
        mod.valueMap = parent.adaptTo(ModifiableValueMap.class);
        if ( mod.valueMap == null ) {
            throw new PreconditionViolatedPersistenceException("Resource at '" + parent.getPath() + "' is not modifiable.");
        }

        final String name = prop.getName();
        if (prop.providesValue()) {
            // if user provided a value, don't mess with it
            setPropertyAsIs(mod, prop);

        } else if (AUTO_PROPS.containsKey(name)) {
            // check if this is a JCR resource and check node type
            if ( this.jcrSupport.isPropertyProtectedOrNewAutoCreated(mod.node, name) ) {
                return;
            }

            // avoid collision with protected properties
            final boolean isNew = jcrSupport.isNewNode(mod.node);
            switch (getAutoType(name)) {
                case CREATED:
                    if (isNew) {
                        setCurrentDate(mod, name);
                    }
                    break;
                case CREATED_BY:
                    if (isNew) {
                        setCurrentUser(mod, name);
                    }
                    break;
                case MODIFIED:
                    setCurrentDate(mod, name);
                    break;
                case MODIFIED_BY:
                    setCurrentUser(mod, name);
                    break;
            }
        } else {
            // no magic field, set value as provided
            setPropertyAsIs(mod, prop);
        }
    }

    /**
     * Sets the property to the given date
     * @param parent parent resource
     * @param name name of the property
     * @throws PersistenceException if a resource error occurs
     */
    private void setCurrentDate(final Modifiable parent, final String name)
    throws PersistenceException {
        removePropertyIfExists(parent, name);
        parent.valueMap.put(name, now);
        changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
    }

    /**
     * set property to the current User id
     * @param parent parent resource
     * @param name name of the property
     * @throws PersistenceException if a resource error occurs
     */
    private void setCurrentUser(final Modifiable parent, final String name)
    throws PersistenceException {
        removePropertyIfExists(parent, name);
        final String user = parent.resource.getResourceResolver().getUserID();
        parent.valueMap.put(name, user);
        changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
    }

    /**
     * Removes the property with the given name from the parent resource if it
     * exists and if it's not a mandatory property.
     *
     * @param parent the parent resource
     * @param name the name of the property to remove
     * @return path of the property that was removed or <code>null</code> if
     *         it was not removed
     * @throws PersistenceException if a repository error occurs.
     */
    private String removePropertyIfExists(final Modifiable parent, final String name)
    throws PersistenceException {
        if (parent.valueMap.containsKey(name) && !jcrSupport.isPropertyMandatory(parent.node, name)) {
            parent.valueMap.remove(name);
            return parent.resource.getPath() + '/' + name;
        }
        return null;
    }

    /**
     * set property without processing, except for type hints
     *
     * @param parent the parent resource
     * @param prop the request property
     * @throws PersistenceException if a resource error occurs.
     */
    private void setPropertyAsIs(final Modifiable parent, final RequestProperty prop)
    throws PersistenceException {

        String[] values = prop.getStringValues();

        // RequestProperty#getStringValues already takes care of the configs ignoreBlanks, defaultValues etc.
        // and provides values as null, new String[0] etc. accordingly.
        if (values == null || (values.length == 1 && values[0].length() == 0)) {
            // if no value is present or a single empty string is given,
            // just remove the existing property (if any)
            removeProperty(parent, prop);

        } else if (values.length == 0) {
            // do not create new prop here, but clear existing
            clearProperty(parent, prop);

        } else {
            // when patching, simply update the value list using the patch operations
            if (prop.isPatch()) {
                values = patch(parent, prop.getName(), values);
                if (values == null) {
                    return;
                }
            }

            final boolean multiValue = isMultiValue(parent, prop, values);

            if (multiValue) {
                // converting single into multi value props requires deleting it first
                removeIfSingleValueProperty(parent, prop);
            }

            final int type = getType(parent, prop);
            if (jcrSupport.hasSession(parent.resource.getResourceResolver())) {

                if (type == PropertyType.DATE) {
                    if (storeAsDate(parent, prop.getName(), values, multiValue)) {
                        return;
                    }
                } else if (isReferencePropertyType(type)) {
                    if (storeAsReference(parent, prop.getName(), values, type, multiValue)) {
                        return;
                    }
                }
            }

            store(parent, prop.getName(), values, type, multiValue);
        }
    }

    /**
     * Patches a multi-value property using add and remove operations per value.
     */
    private String[] patch(final Modifiable parent, String name, String[] values)
    throws PersistenceException {
        // we do not use a Set here, as we want to be very restrictive in our
        // actions and avoid touching elements that are not modified through the
        // add/remove patch operations; e.g. if the value "foo" occurs twice
        // in the existing array, and is not touched, afterwards there should
        // still be two times "foo" in the list, even if this is not a real set.
        List<String> oldValues = new ArrayList<>();

        if (parent.valueMap.containsKey(name)) {
            if ( parent.node != null && !jcrSupport.isPropertyMultiple(parent.node, name)) {

                // can only patch multi-value props
                return null;
            }

            final String[] setValues = parent.valueMap.get(name, String[].class);
            if ( setValues != null ) {
                for(final String v : setValues) {
                    oldValues.add(v);
                }
            }
        }

        boolean modified = false;
        for (String v : values) {
            if (v != null && v.length() > 0) {
                final char op = v.charAt(0);
                final String val = v.substring(1);

                if (op == SlingPostConstants.PATCH_ADD) {
                    if (!oldValues.contains(val)) {
                        oldValues.add(val);
                        modified = true;
                    }
                } else if (op == SlingPostConstants.PATCH_REMOVE) {
                    while (oldValues.remove(val)) {
                        modified = true;
                    }
                }
            }
        }

        // if the patch does not include any operations (e.g. invalid ops)
        // return null to indicate that nothing should be done
        if (modified) {
            return oldValues.toArray(new String[oldValues.size()]);
        }

        return null;
    }


    private boolean isReferencePropertyType(int propertyType) {
        return propertyType == PropertyType.REFERENCE || propertyType == PropertyType.WEAKREFERENCE;
    }

    /**
     * Returns the property type to use for the given property. This is defined
     * either by an explicit type hint in the request or simply the type of the
     * existing property.
     */
    private int getType(final Modifiable parent, RequestProperty prop)
    throws PersistenceException {
        // no explicit typehint
        int type = PropertyType.UNDEFINED;
        if (prop.getTypeHint() != null) {
            try {
                type = PropertyType.valueFromName(prop.getTypeHint());
            } catch (Exception e) {
                // ignore
            }
        }
        String[] values = prop.getStringValues();
        if ( type == PropertyType.UNDEFINED && values != null && values.length > 0 ) {
            final Integer jcrType = jcrSupport.getPropertyType(parent.node, prop.getName());
            if ( jcrType != null ) {
                type = jcrType;
            }
        }
        return type;
    }

    /**
     * Returns whether the property should be handled as multi-valued.
     */
    private boolean isMultiValue(final Modifiable parent, RequestProperty prop, String[] values)
    throws PersistenceException {
        // multiple values are provided
        if (values != null && values.length > 1) {
            return true;
        }
        // TypeHint with []
        if (prop.hasMultiValueTypeHint()) {
            return true;
        }
        // patch method requires multi value
        if (prop.isPatch()) {
            return true;
        }
        // nothing in the request, so check the current JCR property definition
        final Object value = parent.valueMap.get(prop.getName());
        if ( parent.node != null ) {
            if ( value != null ) {
                return jcrSupport.isPropertyMultiple(parent.node, prop.getName());
            }
        } else {
            if ( value != null && value.getClass().isArray() ) {
                return true;
            }
        }
        return false;
    }

    /**
     * Clears a property: sets an empty string for single-value properties, and
     * removes multi-value properties.
     */
    private void clearProperty(final Modifiable parent, RequestProperty prop)
    throws PersistenceException {
        if (parent.valueMap.containsKey(prop.getName())) {
            if ( jcrSupport.isPropertyMultiple(parent.node, prop.getName()) ) {
                // the existing property is multi-valued, so just delete it?
                final String removePath = removePropertyIfExists(parent, prop.getName());
                if ( removePath != null ) {
                    changes.add(Modification.onDeleted(removePath));
                }
            } else {
                parent.valueMap.put(prop.getName(), "");
                changes.add(Modification.onModified(parent.resource.getPath() + '/' + prop.getName()));
            }
        }
    }

    /**
     * Removes the property if it exists.
     */
    private void removeProperty(final Modifiable parent, final RequestProperty prop)
    throws PersistenceException {
        final String removePath = removePropertyIfExists(parent, prop.getName());
        if ( removePath != null ) {
            changes.add(Modification.onDeleted(removePath));
        }
    }

    /**
     * Removes the property if it exists and is single-valued.
     */
    private void removeIfSingleValueProperty(final Modifiable parent,
            final RequestProperty prop)
    throws PersistenceException {
        if (parent.valueMap.containsKey(prop.getName())) {
            if ( jcrSupport.isPropertyMultiple(parent.node, prop.getName()) ) {
                // do nothing, multi value
                return;
            }
            final String removePath = removePropertyIfExists(parent, prop.getName());
            if ( removePath != null ) {
                changes.add(Modification.onDeleted(removePath));
            }
        }
    }

    /**
     * Parses the given source strings and returns the respective Calendar value
     * instances. If no format matches for any of the sources
     * returns <code>null</code>.
     * <p/>
     *
     * @param sources date time source strings
     * @return Calendar value representations of the source or <code>null</code>
     */
    private Calendar[] parse(final String sources[]) {
        final Calendar ret[] = new Calendar[sources.length];
        for (int i=0; i< sources.length; i++) {
            final Calendar c = dateParser.parse(sources[i]);
            if (c == null) {
                return null;
            }
            ret[i] = c;
        }
        return ret;
    }


    /**
     * Stores property value(s) as date(s). Will parse the date(s) from the string
     * value(s) in the {@link RequestProperty}.
     *
     * @return true only if parsing was successful and the property was actually changed
     */
    private boolean storeAsDate(final Modifiable parent, String name, String[] values, boolean multiValued)
    throws PersistenceException {
        if (multiValued) {
            final Calendar[] array = parse(values);
            if (array != null) {
                parent.valueMap.put(name, array);
                changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
                return true;
            }
        } else {
            if (values.length >= 1) {
                final Calendar c = dateParser.parse(values[0]);
                if (c != null) {
                    parent.valueMap.put(name, c);
                    changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));

                    return true;
                }
            }
        }
        return false;
    }

    /**
     * Stores property value(s) as reference(s). Will parse the reference(s) from the string
     * value(s) in the {@link RequestProperty}.
     *
     * @return true only if parsing was successful and the property was actually changed
     */
    private boolean storeAsReference(final Modifiable parent,
            final String name,
            final String[] values,
            final int type,
            final boolean multiValued)
    throws PersistenceException {
        final Modification mod = this.jcrSupport.storeAsReference(parent.resource, parent.node, name, values, type, multiValued);
        return mod != null;
    }

    /**
     * Stores the property as string or via a string value, but with an explicit
     * type. Both multi-value or single-value.
     */
    private void store(final Modifiable parent,
            final String name,
            final String[] values,
            final int type,
            final boolean multiValued)
    throws PersistenceException {
        if ( parent.node != null && type != PropertyType.UNDEFINED ) {
            jcrSupport.setTypedProperty(parent.node, name, values, type, multiValued);

        } else {
            if (multiValued) {
                parent.valueMap.put(name, toJavaObject(values, type));
            } else if (values.length >= 1) {
                parent.valueMap.put(name, toJavaObject(values[0], type));
            }
        }
        changes.add(Modification.onModified(parent.resource.getPath() + '/' + name));
    }

    /** Converts a value */
    private static Object toJavaObject(final String value, final int type) {
        final boolean isEmpty = value == null || value.trim().length() == 0;
        switch (type) {
            case PropertyType.DECIMAL:
                return isEmpty ? BigDecimal.ZERO : new BigDecimal(value);
            case PropertyType.BOOLEAN:
                return isEmpty ? Boolean.FALSE : Boolean.valueOf(value);
            case PropertyType.DOUBLE:
                return isEmpty ? (double)0.0 : Double.valueOf(value);
            case PropertyType.LONG:
                return isEmpty ? 0 : Long.valueOf(value);
            default: // fallback
                return value;
        }
    }

    /** Converts a value */
    private static Object toJavaObject(final String values[], final int type) {
        final Object[] result = new Object[values.length];
        for (int i = 0; i < values.length; i++) {
            if (values[i] != null ) {
                result[i] = toJavaObject(values[i], type);
            }
        }
        return result;
    }


    /**
     * Defines an auto property behavior
     */
    private enum AutoType {
        CREATED,
        CREATED_BY,
        MODIFIED,
        MODIFIED_BY
    }

    public final static class Modifiable {
        public Resource resource;
        public ModifiableValueMap valueMap;
        public Object node;
    }
}
