/*
 * 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.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.SequenceInputStream;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.servlet.ServletContext;

import org.apache.commons.io.IOUtils;
import org.apache.jackrabbit.JcrConstants;
import org.apache.jackrabbit.util.Text;
import org.apache.sling.api.request.RequestParameter;
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.api.resource.ResourceResolver;
import org.apache.sling.api.resource.ValueMap;
import org.apache.sling.servlets.post.Modification;
import org.apache.sling.servlets.post.SlingPostConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Handles file uploads.
 * <p>
 *
 * Simple example:
 * 
 * {@code
 *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
 *     <input type="file" name="./portrait" />
 *   </form>
 * }
 *
 * this will create a nt:file node below "/home/admin" if the node type of
 * "admin" is (derived from) nt:folder, a nt:resource node otherwise.
 * <p>
 *
 * Filename example:
 * {@code
 *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
 *     <input type="file" name="./*" />
 *   </form>
 * }
 *
 * same as above, but uses the filename of the uploaded file as name for the
 * new node.
 * <p>
 *
 * Type hint example:
 * {@code
 *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
 *     <input type="file" name="./portrait" />
 *     <input type="hidden" name="./portrait@TypeHint" value="my:file" />
 *   </form>
 * }
 *
 * this will create a new node with the type my:file below admin. if the hinted
 * type extends from nt:file an intermediate file node is created otherwise
 * directly a resource node.
 */
public class SlingFileUploadHandler {

    private final Logger log = LoggerFactory.getLogger(getClass());

    /**
     * The servlet context.
     */
    private volatile ServletContext servletContext;

    private final JCRSupport jcrSupport = JCRSupport.INSTANCE;

    public void setServletContext(final ServletContext servletContext) {
        this.servletContext = servletContext;
    }

    /**
     * Uses the file(s) in the request parameter for creation of new nodes.
     * if the parent node is a nt:folder a new nt:file is created. otherwise
     * just a nt:resource. if the <code>name</code> is '*', the filename of
     * the uploaded file is used.
     *
     * @param parent the parent node
     * @param prop the assembled property info
     * @throws PersistenceException if an error occurs
     */
    private void setFile(final Resource parentResource,
            final RequestProperty prop,
            final RequestParameter value,
            final List<Modification> changes, String name,
            final String contentType)
    throws PersistenceException {
        // check type hint. if the type is ok and extends from nt:file,
        // create an nt:file with that type. if it's invalid, drop it and let
        // the parent node type decide.
        boolean createNtFile = parentResource.isResourceType(JcrConstants.NT_FOLDER) || this.jcrSupport.isNodeType(parentResource, JcrConstants.NT_FOLDER);
        String typeHint = prop.getTypeHint();
        if (typeHint != null) {
            Boolean isFileNodeType = this.jcrSupport.isFileNodeType(parentResource.getResourceResolver(), typeHint);
            if ( isFileNodeType == null ) {
                // assuming type not valid.
                createNtFile = false;
                typeHint = null;
            } else {
                createNtFile = isFileNodeType;
            }
        }

        // also create an nt:file if the name contains an extension
        // the rationale is that if the file name is "important" we want
        // an nt:file, and an image name with an extension is probably "important"
        if (!createNtFile && name.indexOf('.') > 0) {
            createNtFile = true;
        }

        // set empty type
        if (typeHint == null) {
            typeHint = createNtFile ? JcrConstants.NT_FILE : JcrConstants.NT_RESOURCE;
        }

        // create nt:file resource if needed
        Resource resParent;
        if (createNtFile) {
            // create nt:file
            resParent = getOrCreateChildResource(parentResource, name, typeHint, changes);
            name = JcrConstants.JCR_CONTENT;
            typeHint = JcrConstants.NT_RESOURCE;
        } else {
            resParent = parentResource;
        }

        // create resource
        final Resource newResource = getOrCreateChildResource(resParent, name, typeHint, changes);
        final ModifiableValueMap mvm = newResource.adaptTo(ModifiableValueMap.class);
        // set properties
        mvm.put(JcrConstants.JCR_LASTMODIFIED, Calendar.getInstance());
        mvm.put(JcrConstants.JCR_MIMETYPE, contentType);
        changes.add(Modification.onModified(newResource.getPath() + "/" + JcrConstants.JCR_LASTMODIFIED));
        changes.add(Modification.onModified(newResource.getPath() + "/" + JcrConstants.JCR_MIMETYPE));

        try {
            // process chunk upload request separately
            if (prop.isChunkUpload()) {
                processChunk(resParent, newResource, prop, value, changes);
            } else {
                mvm.put(JcrConstants.JCR_DATA, value.getInputStream());
                changes.add(Modification.onModified(newResource.getPath() + "/" + JcrConstants.JCR_DATA));
            }
        } catch (IOException e) {
            throw new PersistenceException("Error while retrieving inputstream from parameter value.", e);
        }
    }

    /**
     * Process chunk upload. For first and intermediate chunks request persists
     * chunks at jcr:content/chunk_start_end/jcr:data or
     * nt:resource/chunk_start_end/jcr:data. For last last chunk,
     * merge all previous chunks and last chunk and replace binary at
     * destination.
     */
    private void processChunk(final Resource resParent,
            final Resource res,
            final RequestProperty prop,
            final RequestParameter value,
            final List<Modification> changes)
    throws PersistenceException {
        try {
            final ModifiableValueMap mvm = res.adaptTo(ModifiableValueMap.class);
            long chunkOffset = prop.getChunk().getOffset();
            if (chunkOffset == 0) {
                // first chunk
                // check if another chunk upload is already in progress. throw
                // exception
                final Iterator<Resource> itr = new FilteringResourceIterator(res.listChildren(), SlingPostConstants.CHUNK_NODE_NAME);
                if (itr.hasNext()) {
                    throw new PersistenceException(
                        "Chunk upload already in progress at {" + res.getPath()
                            + "}");
                }
                addChunkMixin(mvm);
                mvm.put(SlingPostConstants.NT_SLING_CHUNKS_LENGTH, 0);
                changes.add(Modification.onModified(res.getPath() + "/" + SlingPostConstants.NT_SLING_CHUNKS_LENGTH));
                if (mvm.get(JcrConstants.JCR_DATA) == null ) {
                    // create a empty jcr:data property
                    mvm.put(JcrConstants.JCR_DATA,
                        new ByteArrayInputStream("".getBytes()));
                }
            }
            if (mvm.get(SlingPostConstants.NT_SLING_CHUNKS_LENGTH) == null) {
                throw new PersistenceException("no chunk upload found at {"
                    + res.getPath() + "}");
            }
            long currentLength = mvm.get(SlingPostConstants.NT_SLING_CHUNKS_LENGTH, Long.class);
            long totalLength = prop.getChunk().getLength();
            if (chunkOffset != currentLength) {
                throw new PersistenceException("Chunk's offset {"
                    + chunkOffset
                    + "} doesn't match expected offset {"
                    + currentLength
                    + "}");
            }
            if (totalLength != 0) {
                if (mvm.get(SlingPostConstants.NT_SLING_FILE_LENGTH) != null ) {
                    long expectedLength = mvm.get(
                        SlingPostConstants.NT_SLING_FILE_LENGTH, Long.class);
                    if (totalLength != expectedLength) {
                        throw new PersistenceException("File length {"
                            + totalLength + "} doesn't match expected length {"
                            + expectedLength + "}");
                    }
                } else {
                    mvm.put(SlingPostConstants.NT_SLING_FILE_LENGTH,
                        totalLength);
                }
            }
            final Iterator<Resource> itr = new FilteringResourceIterator(res.listChildren(), SlingPostConstants.CHUNK_NODE_NAME + "_" + String.valueOf(chunkOffset));
            if (itr.hasNext()) {
                throw new PersistenceException("Chunk already present at {"
                    + itr.next().getPath() + "}");
            }
            String nodeName = SlingPostConstants.CHUNK_NODE_NAME + "_"
                + String.valueOf(chunkOffset) + "_"
                + String.valueOf(chunkOffset + value.getSize() - 1);
            if (totalLength == (currentLength + value.getSize())
                || prop.getChunk().isCompleted()) {
                File file = null;
                InputStream fileIns = null;
                try {
                    file = mergeChunks(res, value.getInputStream());
                    fileIns = new FileInputStream(file);
                    mvm.put(JcrConstants.JCR_DATA, fileIns);
                    changes.add(Modification.onModified(res.getPath() + "/" + JcrConstants.JCR_DATA));
                    final Iterator<Resource> rsrcItr = new FilteringResourceIterator(res.listChildren(), SlingPostConstants.CHUNK_NODE_NAME);
                    while (rsrcItr.hasNext()) {
                        Resource rsrcRange = rsrcItr.next();
                        changes.add(Modification.onDeleted(rsrcRange.getPath()));
                        rsrcRange.getResourceResolver().delete(rsrcRange);
                    }
                    if (mvm.get(SlingPostConstants.NT_SLING_FILE_LENGTH) != null) {
                        changes.add(Modification.onDeleted(res.getPath() + "/" + SlingPostConstants.NT_SLING_FILE_LENGTH));
                        mvm.remove(SlingPostConstants.NT_SLING_FILE_LENGTH);
                    }
                    if (mvm.get(SlingPostConstants.NT_SLING_CHUNKS_LENGTH) != null) {
                        changes.add(Modification.onDeleted(res.getPath() + "/" + SlingPostConstants.NT_SLING_CHUNKS_LENGTH));
                        mvm.remove(SlingPostConstants.NT_SLING_CHUNKS_LENGTH);
                    }
                    removeChunkMixin(mvm);
                } finally {
                    try {
                        fileIns.close();
                        file.delete();
                    } catch (IOException ign) {

                    }

                }
            } else {
                final Map<String,Object> props = new HashMap<>();
                props.put(JcrConstants.JCR_DATA, value.getInputStream());
                props.put(SlingPostConstants.NT_SLING_CHUNK_OFFSET, chunkOffset);
                props.put(SlingPostConstants.NT_SLING_CHUNKS_LENGTH, currentLength + value.getSize());
                for(final String key : props.keySet()) {
                    changes.add(Modification.onModified(res.getPath() + "/" + nodeName + "/" + key));
                }
                props.put(ResourceResolver.PROPERTY_RESOURCE_TYPE,
                        SlingPostConstants.NT_SLING_CHUNK_NODETYPE);
                final Resource rangeRsrc = res.getResourceResolver().create(res, nodeName, props);

                changes.add(Modification.onCreated(rangeRsrc.getPath()));
            }
        } catch (IOException e) {
            throw new PersistenceException(
                "Error while retrieving inputstream from parameter value.", e);
        }
    }

    private static final class FilteringResourceIterator implements Iterator<Resource>, Iterable<Resource> {

        private final String prefix;

        private final Iterator<Resource> iter;

        private Resource next;

        public FilteringResourceIterator(final Iterator<Resource> iter, final String prefix) {
            this.prefix = prefix;
            this.iter = iter;
            this.next = seek();
        }

        private Resource seek() {
            Resource result = null;
            while ( iter.hasNext() && result == null ) {
                final Resource c = iter.next();
                if ( c.getName().startsWith(prefix) ) {
                    result = c;
                }
            }
            return result;
        }

        @Override
        public boolean hasNext() {
            return next != null;
        }

        @Override
        public Resource next() {
            final Resource result = next;
            next = seek();
            return result;
        }

        @Override
        public void remove() {
            throw new UnsupportedOperationException();

        }

        @Override
        public Iterator<Resource> iterator() {
            return this;
        }
    }

    /**
     * Merge all previous chunks with last chunk's stream into a temporary file
     * and return it.
     */
    private File mergeChunks(final Resource parentResource,
            final InputStream lastChunkStream)
    throws PersistenceException {
        OutputStream out = null;
        SequenceInputStream  mergeStrm = null;
        File file = null;
        try {
            file = File.createTempFile("tmp-", "-mergechunk");
            out = new FileOutputStream(file);
            String startPattern = SlingPostConstants.CHUNK_NODE_NAME + "_" + "0_";
            Iterator<Resource> itr = new FilteringResourceIterator(parentResource.listChildren(), startPattern);
            final Set<InputStream> inpStrmSet = new LinkedHashSet<>();
            while (itr.hasNext()) {
                final Resource rangeResource = itr.next();
                if (itr.hasNext() ) {
                    throw new PersistenceException(
                        "more than one resource found for pattern: " + startPattern + "*");
                }

                inpStrmSet.add(rangeResource.adaptTo(InputStream.class));
                log.debug("added chunk {} to merge stream", rangeResource.getName());
                String[] indexBounds = rangeResource.getName().substring(
                    (SlingPostConstants.CHUNK_NODE_NAME + "_").length()).split(
                    "_");
                startPattern = SlingPostConstants.CHUNK_NODE_NAME + "_"
                    + String.valueOf(Long.valueOf(indexBounds[1]) + 1) + "_";
                itr = new FilteringResourceIterator(parentResource.listChildren(), startPattern);
            }

            inpStrmSet.add(lastChunkStream);
            mergeStrm = new SequenceInputStream(Collections.enumeration(inpStrmSet));
            IOUtils.copyLarge(mergeStrm, out);
        } catch (final IOException e) {
            throw new PersistenceException("Exception during chunk merge occured: " + e.getMessage(), e);
        } finally {
            IOUtils.closeQuietly(out);
            IOUtils.closeQuietly(mergeStrm);

        }
        return file;
    }

    private Resource getChunkParent(final Resource rsrc) {
        // parent resource containing all chunks and has mixin sling:chunks applied
        // on it.
        Resource chunkParent = null;
        Resource jcrContentNode = null;
        if (hasChunks(rsrc)) {
            chunkParent = rsrc;
        } else {
            jcrContentNode = rsrc.getChild(JcrConstants.JCR_CONTENT);
            if ( hasChunks(jcrContentNode)) {
                chunkParent = jcrContentNode;
            }
        }
        return chunkParent;
    }

    /**
     * Delete all chunks saved within a resource. If no chunks exist, it is no-op.
     * @param rsrc the resource
     * @throws PersistenceException in case of problems
     */
    public void deleteChunks(final Resource rsrc) throws PersistenceException {
        final Resource chunkParent = getChunkParent(rsrc);

        if (chunkParent != null) {
            for(final Resource c : new FilteringResourceIterator(rsrc.listChildren(), SlingPostConstants.CHUNK_NODE_NAME) ) {
                c.getResourceResolver().delete(c);
            }
            final ModifiableValueMap vm = chunkParent.adaptTo(ModifiableValueMap.class);
            vm.remove(SlingPostConstants.NT_SLING_FILE_LENGTH);
            vm.remove(SlingPostConstants.NT_SLING_CHUNKS_LENGTH);
            removeChunkMixin(vm);
        }
    }

    private final void addChunkMixin(final ModifiableValueMap vm) {
        final String[] mixins = vm.get(JcrConstants.JCR_MIXINTYPES, String[].class);
        if ( mixins == null ) {
            vm.put(JcrConstants.JCR_MIXINTYPES, new String[] {SlingPostConstants.NT_SLING_CHUNK_MIXIN});
        } else {
            final Set<String> types = new HashSet<>(Arrays.asList(mixins));
            if ( !types.contains(SlingPostConstants.NT_SLING_CHUNK_MIXIN) ) {
                types.add(SlingPostConstants.NT_SLING_CHUNK_MIXIN);
                vm.put(JcrConstants.JCR_MIXINTYPES, types.toArray(new String[types.size()]));
            }
        }
    }

    private final void removeChunkMixin(final ModifiableValueMap vm) {
        final String[] mixins = vm.get(JcrConstants.JCR_MIXINTYPES, String[].class);
        if ( mixins != null ) {
            final Set<String> types = new HashSet<>(Arrays.asList(mixins));
            if ( types.remove(SlingPostConstants.NT_SLING_CHUNK_MIXIN) ) {
                vm.put(JcrConstants.JCR_MIXINTYPES, types.toArray(new String[types.size()]));
            }
        }
    }

    /**
     * Get the last {@link SlingPostConstants#NT_SLING_CHUNK_NODETYPE}
     * {@link Resource}.
     *
     * @param rsrc {@link Resource} containing
     *            {@link SlingPostConstants#NT_SLING_CHUNK_NODETYPE}
     *            {@link Resource}s
     * @return the {@link SlingPostConstants#NT_SLING_CHUNK_NODETYPE} chunk
     *         resource.
     */
    public Resource getLastChunk(Resource rsrc)  {
        final Resource chunkParent = getChunkParent(rsrc);
        if (chunkParent == null) {
            return null;
        }
        Resource lastChunkRsrc = null;
        long lastChunkStartIndex = -1;
        for(final Resource chunkRsrc : new FilteringResourceIterator(rsrc.listChildren(), SlingPostConstants.CHUNK_NODE_NAME + "_") ) {
            final String[] indexBounds = chunkRsrc.getName().substring(
                     (SlingPostConstants.CHUNK_NODE_NAME + "_").length()).split("_");
            long chunkStartIndex = Long.valueOf(indexBounds[0]);
            if (chunkStartIndex > lastChunkStartIndex) {
                lastChunkRsrc = chunkRsrc;
                lastChunkStartIndex = chunkStartIndex;
            }
        }

        return lastChunkRsrc;
    }

    /**
     * Return true if resource has chunks stored in it, otherwise false.
     */
    private boolean hasChunks(final Resource rsrc) {
        final ValueMap vm = rsrc.getValueMap();
        final String[] mixinTypes = vm.get(JcrConstants.JCR_MIXINTYPES, String[].class);
        if ( mixinTypes != null ) {
            for (final String nodeType : mixinTypes) {
                if (nodeType.equals(SlingPostConstants.NT_SLING_CHUNK_MIXIN)) {
                    return true;
                }
            }
        }
        return false;
    }

    private static final String MT_APP_OCTET = "application/octet-stream";

    /**
     * Uses the file(s) in the request parameter for creation of new nodes.
     * if the parent node is a nt:folder a new nt:file is created. otherwise
     * just a nt:resource. if the <code>name</code> is '*', the filename of
     * the uploaded file is used.
     *
     * @param parent the parent node
     * @param prop the assembled property info
     * @param changes the changes
     * @throws PersistenceException if an error occurs
     */
    public void setFile(final Resource parent, final RequestProperty prop, final List<Modification> changes)
    throws PersistenceException {
        for (final RequestParameter value : prop.getValues()) {

            // ignore if a plain form field or empty
            if (value.isFormField() || value.getSize() <= 0) {
                continue;
            }

            // get node name
            String name = prop.getName();
            if (name.equals("*")) {
                name = value.getFileName();
                // strip of possible path (some browsers include the entire path)
                name = name.substring(name.lastIndexOf('/') + 1);
                name = name.substring(name.lastIndexOf('\\') + 1);
            }
            name = Text.escapeIllegalJcrChars(name);

            // get content type
            String contentType = value.getContentType();
            if (contentType != null) {
                int idx = contentType.indexOf(';');
                if (idx > 0) {
                    contentType = contentType.substring(0, idx);
                }
            }
            if (contentType == null || contentType.equals(MT_APP_OCTET)) {
                // try to find a better content type
                final ServletContext ctx = this.servletContext;
                if (ctx != null) {
                    contentType = ctx.getMimeType(value.getFileName());
                }
                if ( contentType == null ) {
                    contentType = MT_APP_OCTET;
                }
            }

            this.setFile(parent, prop, value, changes, name, contentType);
        }
    }

    private Resource getOrCreateChildResource(final Resource parent,
            final String name,
            final String typeHint,
            final List<Modification> changes)
    throws PersistenceException {
        Resource result = parent.getChild(name);
        if ( result != null ) {
            if ( !result.isResourceType(typeHint) && jcrSupport.isNode(result) && !jcrSupport.isNodeType(result, typeHint) ) {
                parent.getResourceResolver().delete(result);
                result = createWithChanges(parent, name, typeHint, changes);
            }
        } else {
            result = createWithChanges(parent, name, typeHint, changes);
        }
        return result;
    }

    private Resource createWithChanges(final Resource parent, final String name,
            final String typeHint,
            final List<Modification> changes)
    throws PersistenceException {
        Map<String, Object> properties = null;
        if ( typeHint != null ) {
            // sling resource type not allowed for nt:file nor nt:resource
            if ( !jcrSupport.isNode(parent)
                 || (!JcrConstants.NT_FILE.equals(typeHint) && !JcrConstants.NT_RESOURCE.equals(typeHint)) ) {
                properties = Collections.singletonMap(ResourceResolver.PROPERTY_RESOURCE_TYPE, (Object)typeHint);
            } else {
                properties = Collections.singletonMap(JcrConstants.JCR_PRIMARYTYPE, (Object)typeHint);
            }
        }
        final Resource result = parent.getResourceResolver().create(parent, name, properties);
        changes.add(Modification.onCreated(result.getPath()));
        return result;
    }

}