/*
 * 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;

import org.apache.commons.lang3.StringUtils;
import org.apache.sling.api.resource.Resource;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.pipes.internal.BindingProvider;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import static org.apache.commons.lang3.StringUtils.EMPTY;
import static org.apache.sling.pipes.PipeBindings.NN_ADDITIONALBINDINGS;
import static org.apache.sling.pipes.PipeBindings.NN_PROVIDERS;
import static org.apache.sling.pipes.PipeBindings.PN_ADDITIONALSCRIPTS;

/**
 * provides generic utilities for a pipe, is also a dummy pipe (outputs its input, without changing anything)
 */
public class BasePipe implements Pipe {

    private final Logger logger = LoggerFactory.getLogger(BasePipe.class);
    public static final String SLASH = "/";
    public static final String RT_PREFIX = "slingPipes/";
    public static final String RESOURCE_TYPE = RT_PREFIX + "base";
    public static final String DRYRUN_KEY = "dryRun";
    public static final String DRYRUN_EXPR = "${" + DRYRUN_KEY + "}";
    public static final String READ_ONLY = "readOnly";
    public static final String PN_STATUS = "status";
    public static final String PN_STATUS_MODIFIED = "statusModified";
    public static final String PN_BEFOREHOOK = "beforeHook";
    public static final String PN_AFTERHOOK = "afterHook";
    public static final String STATUS_STARTED = "started";
    public static final String STATUS_FINISHED = "finished";

    protected ResourceResolver resolver;
    protected ValueMap properties;
    protected Resource resource;
    protected SuperPipe parent;
    protected String distributionAgent;
    protected PipeBindings bindings;
    protected List<BindingProvider> bindingProviders;

    protected String beforeHook;
    protected String afterHook;

    // used by pipes using complex JCR configurations
    protected static final List<String> IGNORED_PROPERTIES = Arrays.asList("jcr:lastModified", "jcr:primaryType", "jcr:created", "jcr:createdBy", "jcr:uuid");

    Boolean dryRunObject = null;

    @Override
    public SuperPipe getParent() {
        return parent;
    }

    @Override
    public void setParent(SuperPipe parent) {
        this.parent = parent;
    }

    @Override
    public Resource getResource() {
        return resource;
    }

    protected Plumber plumber;

    private String name;

    /**
     * Pipe Constructor
     * @param plumber plumber
     * @param resource configuration resource
     * @param upperBindings already set bindings, can be null
     */
    public BasePipe(@NotNull Plumber plumber, @NotNull Resource resource, @Nullable PipeBindings upperBindings) {
        this.resource = resource;
        properties = resource.getValueMap();
        resolver = resource.getResourceResolver();
        this.plumber = plumber;
        name = properties.get(PN_NAME, resource.getName());
        distributionAgent = properties.get(PN_DISTRIBUTION_AGENT, String.class);
        beforeHook = properties.get(PN_BEFOREHOOK, String.class);
        afterHook = properties.get(PN_AFTERHOOK, String.class);
        extractAdditionalBindings(resource, upperBindings);
    }

    private void fillInProviders(@NotNull Resource additionalBindings) {
        Resource providers = additionalBindings.getChild(NN_PROVIDERS);
        if (providers != null){
            logger.debug("bindings provider are detected");
            bindingProviders = new ArrayList<>();
            for (Resource provider : providers.getChildren()){
                Pipe pipe = plumber.getPipe(provider, bindings);
                if (pipe == null) {
                    logger.error("pipe provided in {} is not correct", provider.getPath());
                } else if (pipe.modifiesContent()) {
                    logger.error("content modifiers like {} are not usable as binding providers", provider.getPath());
                } else {
                    bindingProviders.add(new BindingProvider(pipe));
                }
            }
        }
    }

    /**
     * because additional bindings or scripts can be defined at a sub-pipe level
     * @param resource
     * @param upperBindings
     */
    private void extractAdditionalBindings(@NotNull Resource resource, @Nullable PipeBindings upperBindings) {
        bindings = upperBindings == null ? new PipeBindings(resource) : upperBindings;
        //additional bindings (global variables to use in child pipes expressions)
        Resource additionalBindings = resource.getChild(NN_ADDITIONALBINDINGS);
        if (additionalBindings != null) {
            logger.debug("additional bindings are detected");
            ValueMap additionalMap = additionalBindings.adaptTo(ValueMap.class);
            bindings.addBindings(additionalMap);
            for (String ignoredProperty : BasePipe.IGNORED_PROPERTIES){
                bindings.getBindings().remove(ignoredProperty);
            }
            fillInProviders(additionalBindings);
        }
        Resource scriptsResource = resource.getChild(PN_ADDITIONALSCRIPTS);
        if (scriptsResource != null) {
            String[] scripts = scriptsResource.adaptTo(String[].class);
            if (scripts != null) {
                for (String script : scripts){
                    bindings.addScript(resource.getResourceResolver(), script);
                }
            }
        }
        bindings.addBinding(getName(), EMPTY);
    }

    @Override
    public boolean isDryRun() {
        if (dryRunObject == null) {
            dryRunObject = false;
            if ( bindings.isBindingDefined(DRYRUN_KEY)) {
                Object run = bindings.instantiateObject(DRYRUN_EXPR);
                dryRunObject = true;
                if (run instanceof Boolean) {
                    dryRunObject = (Boolean) run;
                } else if (run == null || (run instanceof String && Boolean.FALSE.toString().equals(run))) {
                    dryRunObject = false;
                }
            }
            logger.debug("setting dryrun object to {}", dryRunObject);
        }
        return dryRunObject;
    }

    @Override
    public String toString() {
        return name + " " + "(path: " + resource.getPath() + ", dryRun: " + isDryRun() + ", modifiesContent: " + modifiesContent() + ")";
    }

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

    @Override
    public String getName(){
        return name;
    }

    /**
     * @return configured expression (not computed)
     */
    public String getRawExpression() {
        return properties.get(PN_EXPR, "");
    }

    /**
     * Get pipe's expression, instanciated or not
     * @return configured expression
     */
    public String getExpr() {
        return bindings.instantiateExpression(getRawExpression());
    }

    /**
     * @return configured input path (not computed)
     */
    protected String getRawPath() {
        return properties.get(PN_PATH, "");
    }

    /**
     * Get pipe's path, instanciated or not
     * @return configured path (can be empty)
     */
    public String getPath() {
        String rawPath = getRawPath();
        return bindings.instantiateExpression(rawPath);
    }

    /**
     * @return computed path: getPath, with relative path taken in account
     */
    protected String getComputedPath() {
        String path = getPath();
        if (StringUtils.isNotBlank(path) && !isRootPath(path) && getPreviousResource() != null) {
            path = getPreviousResource().getPath() + SLASH + path;
        }
        return path;
    }

    /**
     * @param path path to be checked
     * @return true if path is root (aka not relative)
     */
    protected boolean isRootPath(String path){
        return path.startsWith(SLASH);
    }

    /**
     * Retrieves previous pipe if contained by a parent, or referrer's
     * @return pipe before this one or the referrer's can be null in case there is no parent
     */
    protected Pipe getPreviousPipe(){
        return parent != null ? parent.getPreviousPipe(this) : null;
    }

    /**
     * @return previous pipe's output if in a container, null otherwise
     */
    protected Resource getPreviousResource(){
        if (parent != null){
            Pipe previousPipe = getPreviousPipe();
            if (previousPipe != null) {
                return bindings.getExecutedResource(previousPipe.getName());
            }
        }
        return null;
    }

    @Override
    public @Nullable Resource getInput() {
        String path = getComputedPath();
        Resource input = null;
        if (StringUtils.isNotBlank(path)){
            input = resolver.getResource(path);
            if (input == null) {
                logger.warn("configured path {} for {} is not found, expect some troubles...", path, getName());
            }
        } else {
            //no input has been configured: we explicitly expect input to come from previous resource
            input = getPreviousResource();
            if (input == null) {
                logger.warn("no valid path has been configured for {}, and no previous resource to bind on, expect some troubles...",
                    getName());
            }
        }
        logger.debug("input for this pipe is {}", input != null ? input.getPath() : null);
        return input;
    }

    @Override
    public Object getOutputBinding() {
        if (parent != null){
            Resource output = bindings.getExecutedResource(getName());
            if (output != null) {
                return output.adaptTo(ValueMap.class);
            }
        }
        return null;
    }

    @Override
    public PipeBindings getBindings() {
        return bindings;
    }

    /**
     * will execute in parallel binding providers if any, and updated Pipe bindings with returned values
     * @throws InterruptedException can happen while a binding provider is executed
     * @throws ExecutionException can happen when a binding provider is executed
     */
    protected void provideAdditionalBindings() throws InterruptedException, ExecutionException {
        if (bindingProviders != null && !bindingProviders.isEmpty()){
            ExecutorService executor = Executors.newWorkStealingPool();
            List<Future<ValueMap>> additionalBindings = executor.invokeAll(bindingProviders);
            for (Future<ValueMap> additionalBinding : additionalBindings){
                ValueMap binding = additionalBinding.get();
                Pipe pipe = bindingProviders.get(additionalBindings.indexOf(additionalBinding)).getPipe();
                logger.debug("adding binding " +
                        "{}={}", pipe.getName(), binding);
                bindings.addBinding(pipe.getName(), binding);
            }
        }
    }

    /**
     * default execution, just returns current resource
     * @return output of this pipe, which is here the input resource
     */
    public Iterator<Resource> getOutput() {
        try {
            provideAdditionalBindings();
            return computeOutput();
        } catch (Exception e){
            String path = getRawPath();
            if (StringUtils.isBlank(path)){
                Resource input = getPreviousResource();
                if (input != null){
                    path = resource.getPath();
                }
            }
            bindings.setCurrentError(path);
            logger.error("error with pipe execution from {}", path, e);
        }
        return EMPTY_ITERATOR;
    }

    @Override
    public void before() {
        if (StringUtils.isNotBlank(beforeHook)){
            plumber.newPipe(resolver).ref(beforeHook).run();
        }
    }

    @Override
    public void after() {
        if (StringUtils.isNotBlank(afterHook)){
            plumber.newPipe(resolver).ref(afterHook).run();
        }
    }

    /**
     * @return outputs of the pipe, as an iterator of resources
     */
    protected Iterator<Resource> computeOutput() {
        Resource input = getInput();
        if (input != null) {
            return Collections.singleton(input).iterator();
        }
        return EMPTY_ITERATOR;
    }

    /**
     * Get configuration node
     * @return configuration node if any
     */
    public Resource getConfiguration() {
        return resource.getChild(NN_CONF);
    }

    @Override
    public String getDistributionAgent() {
        return distributionAgent;
    }

    /**
     * Empty resource iterator
     */
    public static final Iterator<Resource> EMPTY_ITERATOR = Collections.emptyIterator();
}
