/*
 * 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.util.Text;
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.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, VaultFsLocator fsLocator) {
	    if ( logger == null )
	        throw new RuntimeException("Logger is null");
        if ( fsLocator == null )
            throw new RuntimeException("fsLocator is null");
	    this.logger = logger;
	    this.fsLocator = fsLocator;
	}

    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;
    }
}
