/*
 * 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.apache.sling.servlets.post.impl.operations.JCRSupport;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Handles file uploads.
 * <p/>
 *
 * Simple example:
 * <xmp>
 *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
 *     <input type="file" name="./portrait" />
 *   </form>
 * </xmp>
 *
 * 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:
 * <xmp>
 *   <form action="/home/admin" method="POST" enctype="multipart/form-data">
 *     <input type="file" name="./*" />
 *   </form>
 * </xmp>
 *
 * same as above, but uses the filename of the uploaded file as name for the
 * new node.
 * <p/>
 *
 * Type hint example:
 * <xmp>
 *   <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>
 * </xmp>
 *
 * 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.
     */
    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
     * @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;
    }

}