/*
 *  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.synapse.libraries.util;

import org.apache.axiom.om.OMAttribute;
import org.apache.axiom.om.OMElement;
import org.apache.axiom.om.OMException;
import org.apache.axiom.om.OMXMLBuilderFactory;
import org.apache.axis2.deployment.DeploymentException;
import org.apache.axis2.deployment.util.Utils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.synapse.SynapseException;
import org.apache.synapse.deployers.SynapseArtifactDeploymentException;
import org.apache.synapse.libraries.imports.SynapseImport;
import org.apache.synapse.libraries.model.Library;
import org.apache.synapse.libraries.model.LibraryArtifact;
import org.apache.synapse.libraries.model.SynapseLibrary;

import javax.xml.namespace.QName;
import java.io.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

public class LibDeployerUtils {

    public static final String APP_UNZIP_DIR;

    static {
        String javaTempDir = System.getProperty("java.io.tmpdir");
        APP_UNZIP_DIR = javaTempDir.endsWith(File.separator) ?
                        javaTempDir + LibDeployerConstants.SYNAPSE_LIBS :
                        javaTempDir + File.separator + LibDeployerConstants.SYNAPSE_LIBS;
        createDir(APP_UNZIP_DIR);
    }

    private static final Log log = LogFactory.getLog(LibDeployerUtils.class);



    public static Library createSynapseLibrary(String libPath) {
        createDir(APP_UNZIP_DIR);

        String libFilePath = LibDeployerUtils.formatPath(libPath);
        //extract
        String extractPath = LibDeployerUtils.extractSynapseLib(libFilePath);
        //create synapse lib metadata
        SynapseLibrary synapseLib = LibDeployerUtils.populateDependencies(extractPath +
                                                                          LibDeployerConstants.ARTIFACTS_XML);

        //create a ClassLoader for loading this synapse lib classes/resources
        try {
            ClassLoader libLoader = Utils.getClassLoader(LibDeployerUtils.class.getClassLoader(),
                                                         extractPath, false);
            synapseLib.setLibClassLoader(libLoader);
        } catch (DeploymentException e) {
            throw new SynapseArtifactDeploymentException("Error setting up lib classpath for Synapse" +
                                                         " Library  : " + libFilePath, e);
        }
        //resolve synapse lib artifacts
        LibDeployerUtils.searchAndResolveDependencies(extractPath, synapseLib);
        return synapseLib;
    }

    /**
     * populate Dependencies using main root artifacts.xml.. Schema for artifacts.xml is follwing
     *
     *<artifacts>
         <artifact name="SampleLib" package="synapse.sample" >
                <dependency artifact="templates1" /> +
                <description>sample synapse library</description> ?
         </artifact>
    </artifacts>
     *
     * @param libXmlPath
     * @return
     */
    private static SynapseLibrary populateDependencies(String libXmlPath) {
        File f = new File(libXmlPath);
        if (!f.exists()) {
            throw new SynapseException("artifacts.xml file not found at : " + libXmlPath);
        }
        InputStream xmlInputStream = null;
        try {
            xmlInputStream = new FileInputStream(f);
            OMElement documentElement = OMXMLBuilderFactory.createOMBuilder(xmlInputStream).getDocumentElement();
            if (documentElement == null) {
                throw new SynapseArtifactDeploymentException("Document element for artifacts.xml is " +
                                                             "null. Can't build " +
                                                             "the synapse library configuration");
            }
            Iterator artifactItr = documentElement.getChildrenWithLocalName(LibDeployerConstants.ARTIFACT);
            SynapseLibrary mainSynLibArtifact = null;
            mainSynLibArtifact = createSynapseLibraryWithDeps(((OMElement) artifactItr.next()));
            if (mainSynLibArtifact == null) {
                throw new SynapseArtifactDeploymentException("artifacts.xml is invalid. <artifact> element" +
                                                             " Not Found ");
            }
            return mainSynLibArtifact;
        } catch (FileNotFoundException e) {
            throw new SynapseArtifactDeploymentException("artifacts.xml File cannot be loaded from " + libXmlPath, e);

        } catch (OMException e) {
            throw new SynapseArtifactDeploymentException("Error while parsing the artifacts.xml file ", e);
        } finally {
            if (xmlInputStream != null) {
                try {
                    xmlInputStream.close();
                } catch (IOException e) {
                    log.error("Error while closing input stream.", e);
                }
            }
        }
    }

    /**
     * Builds the Artifact object when an artifact element is given
     *
     * @param artifactEle - artifact OMElement
     * @return created Artifact object
     */
    private static SynapseLibrary createSynapseLibraryWithDeps(OMElement artifactEle) {
        if (artifactEle == null) {
            return null;
        }
        SynapseLibrary synLib = new SynapseLibrary(readAttribute(artifactEle, LibDeployerConstants.NAME),
                                                   readAttribute(artifactEle, LibDeployerConstants.PACKAGE_ATTR));
        synLib.setDescription(readChildText(artifactEle,LibDeployerConstants.DESCRIPTION_ELEMENT));
        // read the dependencies
        Iterator itr = artifactEle.getChildrenWithLocalName(LibDeployerConstants.DEPENDENCY);
        while (itr.hasNext()) {
            OMElement depElement = (OMElement) itr.next();
            // create a synLib for each dependency and add to the root synLib
            LibraryArtifact.Dependency dep = new LibraryArtifact.Dependency(readAttribute(depElement,
                                                                     LibDeployerConstants.ARTIFACT));
            synLib.addDependency(dep);
        }

        return synLib;
    }


    /**
     * Deploys all artifacts under a root artifact..
     *
     * @param rootDirPath - root dir of the extracted artifact
     * @param library     - lib instance
     */
    private static void searchAndResolveDependencies(String rootDirPath,
                                                    SynapseLibrary library) {
        List<LibraryArtifact> libraryArtifacts = new ArrayList<LibraryArtifact>();
        File extractedDir = new File(rootDirPath);
        File[] allFiles = extractedDir.listFiles();
        if (allFiles == null) {
            return;
        }


        // search for all directories under the extracted path
        for (File artifactDirectory : allFiles) {
            if (!artifactDirectory.isDirectory()) {
                continue;
            }

            String directoryPath = formatPath(artifactDirectory.getAbsolutePath());
            String artifactXmlPath = directoryPath + File.separator + LibDeployerConstants.ARTIFACT_XML;

            File f = new File(artifactXmlPath);
            // if the artifact.xml not found, ignore this dir
            if (!f.exists()) {
                continue;
            }

            LibraryArtifact artifact = null;
            InputStream xmlInputStream = null;
            try {
                xmlInputStream = new FileInputStream(f);
                artifact = buildArtifact(library, xmlInputStream, directoryPath);
            } catch (FileNotFoundException e) {
                log.warn("Error while resolving synapse lib dir :"
                                                             + artifactDirectory.getName() +
                                                             " artifacts.xml File cannot be loaded " +
                                                             "from " + artifactXmlPath, e);
            } catch (Exception e) {
                log.warn("Error ocurred while resolving synapse lib dir :"
                                                             + artifactDirectory.getName() +
                                                             " for artifacts.xml path" + artifactXmlPath, e);
            } finally {
                if (xmlInputStream != null) {
                    try {
                        xmlInputStream.close();
                    } catch (IOException e) {
                        log.error("Error while closing input stream.", e);
                    }
                }
            }

            if (artifact == null) {
                log.warn("Could not build lib artifact for path : " + directoryPath + " Synapse Library :" +
                         library.getQName() + ". Continue searching for other lib artifacts");
                continue;

            }
            libraryArtifacts.add(artifact);
        }
        boolean isDepsResolved = library.resolveDependencies(libraryArtifacts);
        if (!isDepsResolved) {
            throw new SynapseArtifactDeploymentException("Error when resolving Dependencies for lib : " + library.toString());
        }
    }

    /**
     * Builds the artifact from the given input steam and adds it as a dependency in the provided
     *  parent Synapse library artifact
     *
     * @param library
     * @param artifactXmlStream - xml input stream of the artifact.xml
     * @param directoryPath
     * @return - Artifact instance if successfull. otherwise null..
     */
    private static LibraryArtifact buildArtifact(SynapseLibrary library, InputStream artifactXmlStream, String directoryPath) {
        LibraryArtifact artifact = null;
        try {
            OMElement artElement = OMXMLBuilderFactory.createOMBuilder(artifactXmlStream).getDocumentElement();

            if (LibDeployerConstants.ARTIFACT.equals(artElement.getLocalName())) {
                artifact = populateLibraryArtifact(artElement, directoryPath, null, library);
            } else {
                log.error("artifact.xml is invalid. Error occurred while resolving Synapse Library : "
                          + library.getQName());
                return null;
            }
        } catch (OMException e) {
            throw new SynapseArtifactDeploymentException("Error parsing artifact.xml for path : " +
                                                         directoryPath ,e);
        }

        if (artifact == null || artifact.getName() == null) {
            log.error("Invalid artifact found in Synapse Library : "
                      + library.getQName() );
            return null;
        }
        return artifact;
    }


    /**
     * Builds the Artifact object when an root artifact element is given . Schema for artifact.xml
     * is as follows
     * <artifact name="templates1" type="synapse/template" >

        <subArtifacts>
            <artifact name="greet_func1" >
                    <file>templ1_ns1.xml</file>
                    <description>sample synapse library artifact Description</description> ?
            </artifact> *
        </subArtifacts> *

        <description>sample synapse library artifact Description</description> ?
    </artifact>
     *
     * @param artifactEle - artifact OMElement
     * @return created Artifact object
     */
    private static LibraryArtifact populateLibraryArtifact(OMElement artifactEle, String artifactPath,
                                                          LibraryArtifact parent , SynapseLibrary library) {
        if (artifactEle == null || artifactPath == null ) {
            return null;
        }

        LibraryArtifact artifact = new LibraryArtifact(readAttribute(artifactEle, LibDeployerConstants.NAME));
        artifact.setParent(parent);
        artifact.setType(readAttribute(artifactEle, LibDeployerConstants.TYPE));
        artifact.setPath(artifactPath);

        artifact.setDescription(readChildText(artifactEle,LibDeployerConstants.DESCRIPTION_ELEMENT));
        //add a description of this artifact(if availalbe) to Synapse Library
        library.addArtifactDescription(artifact);
        // read the subArtifacts
        OMElement subArtifactsElement = artifactEle
                .getFirstChildWithName(new QName(LibDeployerConstants.SUB_ARTIFACTS));
        if (subArtifactsElement != null) {
            Iterator subArtItr = subArtifactsElement.getChildrenWithLocalName(LibDeployerConstants.ARTIFACT);
            while (subArtItr.hasNext()) {
                // as this is also an artifact, use recursion
                LibraryArtifact subArtifact = populateLibraryArtifact((OMElement) subArtItr.next(), artifactPath, artifact, library);
                artifact.addSubArtifact(subArtifact);
            }
        }

        // read and check for files
        Iterator fileItr = artifactEle.getChildrenWithLocalName(LibDeployerConstants.FILE);
        while (fileItr.hasNext()) {
            OMElement fileElement = (OMElement) fileItr.next();
            artifact.setupFile(fileElement.getText());
        }
        return artifact;
    }

    public static void loadLibArtifacts(SynapseImport synImport, Library library) {
        if (synImport.getLibName().equals(library.getQName().getLocalPart()) &&
            synImport.getLibPackage().equals(library.getPackage())) {
            library.loadLibrary();
        }
    }

    public static <T> T getLibArtifact(Map<String, Library> librarySet, String key, Class<T> type) {
        for (Library synapseLibrary : librarySet.values()) {
            try {
                T artifact = (T) synapseLibrary.getArtifact(key);
                if (artifact != null) {
                    return artifact;
                }
            } catch (Exception e) {
                //ignore
            }
        }
        return null;
    }

    public static String getQualifiedName(SynapseImport synImport){
        return new QName(synImport.getLibPackage(),synImport.getLibName()).toString();
    }


    ///////////////////////
    ////////////////// Start Common Utility Methods
    /**
     * Reads an attribute in the given element and returns the value of that attribute
     *
     * @param element - Element to search
     * @param attName - attribute name
     * @return if the attribute found, return value. else null.
     */
    public static String readAttribute(OMElement element, String attName) {
        if (element == null) {
            return null;
        }
        OMAttribute temp = element.getAttribute(new QName(attName));
        if (temp != null) {
            return temp.getAttributeValue();
        }
        return null;
    }

    public static String readChildText(OMElement element, String ln) {
        return readChildText(element, ln, null);
    }

    /**
     * Reads a text node which is in a child element of the given element and returns the text
     * value.
     *
     * @param element - Element to search
     * @param ln      - Child element name
     * @param ns      - Child element namespace
     * @return if the child text element found, return text value. else null.
     */
    public static String readChildText(OMElement element, String ln, String ns) {
        if (element == null) {
            return null;
        }
        OMElement temp = element.getFirstChildWithName(new QName(ns, ln));
        if (temp != null) {
            return temp.getText();
        }
        return null;
    }


    /**
     * Extract the Synapse Library at the provided path to the java temp dir. Return the
     * extracted location
     *
     * @param libPath - Absolute path of the Synapse Lib archive file
     * @return - extracted location
     * @throws SynapseException - error on extraction
     */
    public static String extractSynapseLib(String libPath) throws SynapseException {
        libPath = formatPath(libPath);
        String fileName = libPath.substring(libPath.lastIndexOf('/') + 1);
        String dest = APP_UNZIP_DIR + File.separator + System.currentTimeMillis() +
                      fileName + File.separator;
        createDir(dest);

        try {
            extract(libPath, dest);
        } catch (IOException e) {
            throw new SynapseException("Error while extracting Synapse Library : " + fileName, e);
        }
        return dest;
    }

    /**
     * Format the string paths to match any platform.. windows, linux etc..
     *
     * @param path - input file path
     * @return formatted file path
     */
    public static String formatPath(String path) {
        // removing white spaces
        path = path.replaceAll("\\b\\s+\\b", "%20");
        // replacing all "\" with "/"
        return path.replace('\\', '/');
    }

    private static void extract(String sourcePath, String destPath) throws IOException {
        Enumeration entries;
        ZipFile zipFile;

        zipFile = new ZipFile(sourcePath);
        entries = zipFile.entries();

        while (entries.hasMoreElements()) {
            ZipEntry entry = (ZipEntry) entries.nextElement();
            // we don't need to copy the META-INF dir
            if (entry.getName().startsWith("META-INF/")) {
                continue;
            }
            // if the entry is a directory, create a new dir
            if (entry.isDirectory()) {
                createDir(destPath + entry.getName());
                continue;
            }
            // if the entry is a file, write the file
            copyInputStream(zipFile.getInputStream(entry),
                            new BufferedOutputStream(new FileOutputStream(destPath + entry.getName())));
        }
        zipFile.close();
    }


    public static void createDir(String path) {
        File temp = new File(path);
        if (!temp.exists() && !temp.mkdir()) {
            log.error("Error while creating directory : " + path);
        }
    }

    private static void copyInputStream(InputStream in, OutputStream out)
            throws IOException {
        byte[] buffer = new byte[40960];
        int len;

        while ((len = in.read(buffer)) >= 0) {
            out.write(buffer, 0, len);
        }

        in.close();
        out.close();
    }

    /////////////////// End Of Common Utility Methods


    public static void main(String[] args) {
        new SynapseLibrary(null, null).resolveDependencies(null);
    }
}
