/*
 * 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.ide.impl.vlt.serialization;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.ListIterator;

import javax.jcr.Credentials;
import javax.jcr.Node;
import javax.jcr.PathNotFoundException;
import javax.jcr.Repository;
import javax.jcr.RepositoryException;
import javax.jcr.Session;
import javax.jcr.Value;
import javax.jcr.ValueFormatException;
import javax.jcr.nodetype.NodeType;

import org.apache.jackrabbit.vault.fs.api.Aggregate;
import org.apache.jackrabbit.vault.fs.api.Aggregator;
import org.apache.jackrabbit.vault.fs.api.RepositoryAddress;
import org.apache.jackrabbit.vault.fs.api.VaultFile;
import org.apache.jackrabbit.vault.fs.api.VaultFileSystem;
import org.apache.jackrabbit.vault.fs.config.ConfigurationException;
import org.apache.jackrabbit.vault.fs.impl.aggregator.FileAggregator;
import org.apache.jackrabbit.vault.fs.impl.aggregator.GenericAggregator;
import org.apache.jackrabbit.vault.fs.impl.io.DocViewSerializer;
import org.apache.jackrabbit.vault.util.Constants;
import org.apache.jackrabbit.vault.util.JcrConstants;
import org.apache.jackrabbit.vault.util.MimeTypes;
import org.apache.jackrabbit.vault.util.PlatformNameFormat;
import org.apache.jackrabbit.vault.util.Text;
import org.apache.sling.ide.impl.vlt.VaultFsLocator;
import org.apache.sling.ide.jcr.RepositoryUtils;
import org.apache.sling.ide.log.Logger;
import org.apache.sling.ide.serialization.SerializationData;
import org.apache.sling.ide.serialization.SerializationDataBuilder;
import org.apache.sling.ide.serialization.SerializationException;
import org.apache.sling.ide.serialization.SerializationKind;
import org.apache.sling.ide.serialization.SerializationKindManager;
import org.apache.sling.ide.transport.ResourceProxy;

public class VltSerializationDataBuilder implements SerializationDataBuilder {

    private VaultFsLocator fsLocator;
    private SerializationKindManager skm;
	private org.apache.sling.ide.transport.Repository repo;
	private Session session;
	private VaultFileSystem fs;
    private Logger logger;
	
	public VltSerializationDataBuilder(Logger logger) {
	    this.logger = logger;
	}

    public void init(org.apache.sling.ide.transport.Repository repository, File contentSyncRoot)
            throws SerializationException {

    	this.repo = repository;
    	
        try {
            this.skm = new SerializationKindManager();
            this.skm.init(repository);
            if (!contentSyncRoot.exists()) {
            	throw new IllegalArgumentException("contentSyncRoot does not exist: "+contentSyncRoot);
            }

            Repository jcrRepo = RepositoryUtils.getRepository(repo.getRepositoryInfo());
            Credentials credentials = RepositoryUtils.getCredentials(repo.getRepositoryInfo());
            
            session = jcrRepo.login(credentials);

            RepositoryAddress address = RepositoryUtils.getRepositoryAddress(repo.getRepositoryInfo());

            fs = fsLocator.getFileSystem(address, contentSyncRoot, session);
        
        } catch (org.apache.sling.ide.transport.RepositoryException e) {
            throw new SerializationException(e);
        } catch (RepositoryException e) {
            throw new SerializationException(e);
		} catch (IOException e) {
            throw new SerializationException(e);
		} catch (ConfigurationException e) {
            throw new SerializationException(e);
		}
    }
    
    @Override
    public void destroy() {
        if (session != null) {
            session.logout();
        }
    }

    @Override
    public SerializationData buildSerializationData(File contentSyncRoot, ResourceProxy resource) throws SerializationException {

        try {

            List<Aggregate> chain = findAggregateChain(resource);

            if (chain == null) {
            	return null;
            }

            Aggregate aggregate = chain.get(chain.size() - 1);

            String fileOrFolderPathHint = calculateFileOrFolderPathHint(chain);

            String nameHint = PlatformNameFormat.getPlatformName(aggregate.getName());

            SerializationKind serializationKind = getSerializationKind(aggregate);

            if (resource.getPath().equals("/") || serializationKind == SerializationKind.METADATA_PARTIAL
                    || serializationKind == SerializationKind.FILE || serializationKind == SerializationKind.FOLDER) {
                nameHint = Constants.DOT_CONTENT_XML;
            } else if (serializationKind == SerializationKind.METADATA_FULL) {
                nameHint += ".xml";
            }

           logger.trace("Got location {0} for path {1}", fileOrFolderPathHint, resource.getPath());

            if (!needsDir(aggregate)) {
                return SerializationData.empty(fileOrFolderPathHint, serializationKind);
            }

            DocViewSerializer s = new DocViewSerializer(aggregate);
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            s.writeContent(out);
            
            byte[] result = out.toByteArray();

            return new SerializationData(fileOrFolderPathHint, nameHint, result, serializationKind);

        } catch (RepositoryException e) {
            throw new SerializationException(e);
        } catch (IOException e) {
            throw new SerializationException(e);
        }
    }

    private SerializationKind getSerializationKind(Aggregate aggregate) throws RepositoryException {

        NodeType[] mixinNodeTypes = aggregate.getNode().getMixinNodeTypes();
        List<String> mixinNodeTypeNames = new ArrayList<>(mixinNodeTypes.length);
        for (NodeType nodeType : mixinNodeTypes)
            mixinNodeTypeNames.add(nodeType.getName());

        return skm.getSerializationKind(aggregate.getNode()
                .getPrimaryNodeType()
                .getName(), mixinNodeTypeNames);
    }

    private boolean needsDir(Aggregate aggregate) throws RepositoryException, PathNotFoundException,
            ValueFormatException {

        Aggregator aggregator = fs.getAggregateManager().getAggregator(aggregate.getNode(), null);
        boolean needsDir = true;
        if (aggregator instanceof FileAggregator) {
            needsDir = false;
            // TODO - copy-pasted from FileAggregator, and really does not belong here...
            Node content = aggregate.getNode();
            if (content.isNodeType(JcrConstants.NT_FILE)) {
                content = content.getNode(JcrConstants.JCR_CONTENT);
            }
            String mimeType = null;
            if (content.hasProperty(JcrConstants.JCR_MIMETYPE)) {
                try {
                    mimeType = content.getProperty(JcrConstants.JCR_MIMETYPE).getString();
                } catch (RepositoryException e) {
                    // ignore
                }
            }
            if (mimeType == null) {
                // guess mime type from name
                mimeType = MimeTypes.getMimeType(aggregate.getNode().getName(),
                        MimeTypes.APPLICATION_OCTET_STREAM);
            }

            needsDir = !MimeTypes.matches(aggregate.getNode().getName(), mimeType,
                    MimeTypes.APPLICATION_OCTET_STREAM);

            if (!needsDir) {
                if (content.hasProperty(JcrConstants.JCR_MIXINTYPES)) {
                    for (Value v : content.getProperty(JcrConstants.JCR_MIXINTYPES).getValues()) {
                        if (!v.getString().equals(JcrConstants.MIX_LOCKABLE)) {
                            needsDir = true;
                            break;
                        }
                    }
                }
            }

         // TODO - copy-pasted from GenericAggregator
        } else if (aggregator instanceof GenericAggregator) {
            if (isPlainNtFolder(aggregate)) {
                needsDir = false;
            }
        }
        return needsDir;
    }

    private String calculateFileOrFolderPathHint(List<Aggregate> chain) throws RepositoryException {

        ListIterator<Aggregate> aggs = chain.listIterator();
        StringBuilder out = new StringBuilder();
        while (aggs.hasNext()) {
            Aggregate cur = aggs.next();
            if (aggs.previousIndex() == 0) {
                out.append(PlatformNameFormat.getPlatformPath(cur.getPath()));
            } else {
                out.append("/");
                out.append(PlatformNameFormat.getPlatformPath(cur.getRelPath()));
            }

            if (needsDir(cur)) {
                SerializationKind serializationKind = getSerializationKind(cur);

                if (serializationKind == SerializationKind.FILE) {
                    out.append(".dir");
                }

                if (!aggs.hasNext() && serializationKind == SerializationKind.METADATA_FULL) {
                    out.delete(out.lastIndexOf("/"), out.length());
                }
            }
        }

        return out.toString();
    }

    private boolean isPlainNtFolder(Aggregate agg) throws RepositoryException {

        return agg.getNode().getPrimaryNodeType().getName().equals("nt:folder")
                && agg.getNode().getMixinNodeTypes().length == 0;
    }

    /**
     * Returns the aggregates for a specific resource
     * 
     * <p>
     * In the simplest case, a single element is returned in the chain, signalling that the aggregate is a top-level
     * one.
     * </p>
     * 
     * <p>
     * For leaf aggregates, the list contains the top-most aggregates first and ends up with the leaf-most ones.
     * </p>
     * 
     * @param resource the resource to find the aggregate chain for
     * @return a list of aggregates
     * @throws IOException
     * @throws RepositoryException
     */
    private List<Aggregate> findAggregateChain(ResourceProxy resource) throws IOException, RepositoryException {

        VaultFile vaultFile = fs.getFile(PlatformNameFormat.getPlatformPath(resource.getPath()));

        if (vaultFile == null || vaultFile.getAggregate() == null) {
                // this file might be a leaf aggregate of a vaultfile higher in the resource path ; so look for a
                // parent higher

            String parentPath = Text.getRelativeParent(resource.getPath(), 1);
            while (!parentPath.equals("/")) {
                VaultFile parentFile = fs.getFile(PlatformNameFormat.getPlatformPath(parentPath));

                if (parentFile != null) {
                    Aggregate parentAggregate = parentFile.getAggregate();
                    ArrayList<Aggregate> parents = new ArrayList<>();
                    parents.add(parentAggregate);
                    List<Aggregate> chain = lookForAggregateInLeaves(resource, parentAggregate, parents);
                    if (chain != null) {
                        return chain;
                    }
                }

                parentPath = Text.getRelativeParent(parentPath, 1);
            }

            return null;
        }


        return Collections.singletonList(vaultFile.getAggregate());
    }

    /**
     * Recursively looks for an aggregate matching the <tt>resource</tt>'s path starting at the <tt>parentAggregate</tt>
     * 
     * <p>
     * The returned chain will contain at least one aggregate, in case the resource is contained in a stand-alone (?)
     * aggregate, or multiple aggregates in case the matching aggregate is a leaf one.
     * </p>
     * 
     * @param resource the resource
     * @param parentAggregate the known parent aggregate which potentially matches this resource
     * @param chain the chain used to record all intermediate aggregates
     * @return the final aggregate chain
     * 
     * @throws RepositoryException
     */
    private List<Aggregate> lookForAggregateInLeaves(ResourceProxy resource, Aggregate parentAggregate,
            List<Aggregate> chain) throws RepositoryException {

        if (parentAggregate == null) {
            return null;
        }

        List<? extends Aggregate> leaves = parentAggregate.getLeaves();
        if (leaves == null) {
            return null;
        }

        for (Aggregate leaf : leaves) {
            if (leaf.getPath().equals(resource.getPath())) {
                chain.add(leaf);
                return chain;
            } else if (Text.isDescendant(leaf.getPath(), resource.getPath())) {
                chain.add(leaf);
                return lookForAggregateInLeaves(resource, leaf, chain);
            }
        }

        return null;
    }

    public void setLocator(VaultFsLocator locator) {

        this.fsLocator = locator;
    }

}
