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

import org.apache.sling.api.resource.ModifiableValueMap;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.pipes.BasePipe;
import org.apache.sling.pipes.PipeBindings;
import org.apache.sling.pipes.Plumber;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.jcr.Node;
import javax.jcr.NodeIterator;
import javax.jcr.Property;
import javax.jcr.RepositoryException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * pipe that writes to configured resource
 */
public class WritePipe extends BasePipe {
    private static final Logger logger = LoggerFactory.getLogger(WritePipe.class);
    public static final String RESOURCE_TYPE = RT_PREFIX + "write";
    protected static final Pattern ADD_PATCH = Pattern.compile("\\+\\[(.*)\\]");
    protected static final Pattern MULTI = Pattern.compile("\\[(.*)\\]");

    Node confTree;
    private List<Resource> propertiesToRemove;

    /**
     * public constructor
     * @param plumber plumber instance
     * @param resource configuration resource
     * @param upperBindings super pipe's bindings
     */
    public WritePipe(Plumber plumber, Resource resource, PipeBindings upperBindings) {
        super(plumber, resource, upperBindings);
        if (getConfiguration() == null){
            String pathCandidate = getExpr();
            Resource candidate = resolver.getResource(pathCandidate);
            if (candidate  != null) {
                confTree = candidate.adaptTo(Node.class);
            } else {
                throw new IllegalArgumentException("write pipe is mis-configured: it should have a configuration node, or an expression");
            }
        } else {
            confTree = getConfiguration().adaptTo(Node.class);
        }
    }


    /**
     * convert the configured string value (can be an expression) in a value that can be written in a resource.
     * also handles patch for multivalue properties like <code>+[value]</code> in which case <code>value</code>
     * is added to the MV property
     * @param resource resource to which value will be written
     * @param key property to which value will be written
     * @param expression configured value to write
     * @return actual value to write to the resource
     */
    protected Object computeValue(Resource resource, String key, String expression) {
        Object value = bindings.instantiateObject(expression);
        if (value instanceof String) {
            //in that case we treat special case like MV or patches
            String sValue = (String)value;
            Matcher patch = ADD_PATCH.matcher(sValue);
            if (patch.matches()) {
                String newValue = patch.group(1);
                String[] actualValues = resource.getValueMap().get(key, String[].class);
                List<String> newValues = actualValues != null ? new LinkedList<>(Arrays.asList(actualValues)) : new ArrayList<>();
                if (!newValues.contains(newValue)) {
                    newValues.add(newValue);
                }
                return newValues.toArray(new String[newValues.size()]);
            }
            Matcher multiMatcher = MULTI.matcher(sValue);
            if (multiMatcher.matches()) {
                return multiMatcher.group(1).split(",");
            }
        }
        return value;
    }

    /**
     * convert the configured string value (can be an expression) in a value that can be written in a resource.
     * also handles patch for multivalue properties like <code>+[value]</code> in which case <code>value</code>
     * is added to the MV property
     * @param resource resource to which value will be written
     * @param key property to which value will be written
     * @param expression configured value to write
     * @return actual value to write to the resource
     */
    protected Object computeValue(Resource resource, String key, Object expression)  {
        if (expression instanceof String) {
            return computeValue(resource, key, (String)expression);
        } else if (expression instanceof String[]){
            List<String> values = new ArrayList<>();
            for (String expr : (String[])expression){
                values.add((String)computeValue(resource, key, expr));
            }
            return values.toArray(new String[values.size()]);
        }
        return expression;
    }

    @Override
    public boolean modifiesContent() {
        return true;
    }

    /**
     * Write properties from the configuration to the target resource,
     * instantiating both property names & values
     *
     * @param conf configured resource that holds all properties to write (and subpipes)
     * @param target target resource on which configured values will be written
     */
    private void copyProperties(@Nullable Resource conf, Resource target)  {
        ValueMap writeMap = conf != null ? conf.adaptTo(ValueMap.class) : null;
        ModifiableValueMap properties = target.adaptTo(ModifiableValueMap.class);

        //writing current node
        if (properties != null && writeMap != null) {
            for (Map.Entry<String, Object> entry : writeMap.entrySet()) {
                if (!IGNORED_PROPERTIES.contains(entry.getKey())) {
                    String key = parent != null ? bindings.instantiateExpression(entry.getKey()) : entry.getKey();
                    Object value = computeValue(target, key, entry.getValue());
                    if (value == null) {
                        //null value are not handled by modifiable value maps,
                        //removing the property if it exists
                        addPropertyToRemove(target.getChild(key));
                    } else {
                        logger.info("writing {}@{}={}", target.getPath(), key, value);
                        if (!isDryRun()){
                            properties.put(key, value);
                        }
                    }
                }
            }
        }
    }

    /**
     * we store all property to remove for very last moment (in order to potentially reuse their value)
     * @param property property resource that should be removed
     */
    private void addPropertyToRemove(Resource property){
        if (property != null) {
            if (propertiesToRemove == null) {
                propertiesToRemove = new ArrayList<>();
            }
            propertiesToRemove.add(property);
        }
    }

    /**
     * write the configured tree at the target resource, creating each node if needed, copying values.
     * @param conf configuration JCR tree to write to target resource
     * @param target target resource to write
     */
    private void writeTree(Node conf, Resource target) throws RepositoryException {
        copyProperties(resolver.getResource(conf.getPath()), target);
        NodeIterator childrenConf = conf.getNodes();
        if (childrenConf.hasNext()){
            Node targetNode = target.adaptTo(Node.class);
            if (targetNode != null) {
                logger.info("dubbing {} at {}", conf.getPath(), target.getPath());
                while (childrenConf.hasNext()){
                    Node childConf = childrenConf.nextNode();
                    String name = childConf.getName();
                    name = bindings.conditionalString(name);
                    if (name == null){
                        logger.debug("name has been instantiated as null, not writing that tree");
                    } else if (!isDryRun()){
                        Node childTarget = targetNode.hasNode(name) ? targetNode.getNode(name) : targetNode.addNode(name, childConf.getPrimaryNodeType().getName());
                        logger.debug("writing tree {}", childTarget.getPath());
                        writeTree(childConf, resolver.getResource(childTarget.getPath()));
                    }
                }
            }
        }
    }


    @Override
    protected Iterator<Resource> computeOutput() {
        try {
            Resource resource = getInput();
            if (resource != null) {
                writeTree(confTree, resource);
                if (propertiesToRemove != null && !propertiesToRemove.isEmpty()){
                    for (Resource propertyResource : propertiesToRemove) {
                        logger.info("removing {}", propertyResource.getPath());
                        if (!isDryRun()){
                            Property property = propertyResource.adaptTo(Property.class);
                            if (property != null) {
                                property.remove();
                            }
                        }
                    }
                }
                return super.computeOutput();
            }
        } catch (RepositoryException e) {
            throw new IllegalStateException(e);
        } finally {
            if (propertiesToRemove != null){
                propertiesToRemove.clear();
            }
        }
        return EMPTY_ITERATOR;
    }
}
