/*
 * 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.flex.utilities.converter;

import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateExceptionHandler;
import org.apache.flex.utilities.converter.api.ProxySettings;
import org.apache.flex.utilities.converter.exceptions.ConverterException;
import org.apache.flex.utilities.converter.model.MavenArtifact;
import org.codehaus.jettison.json.JSONArray;
import org.codehaus.jettison.json.JSONException;
import org.codehaus.jettison.json.JSONObject;
import org.codehaus.jettison.json.JSONTokener;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.xml.sax.SAXException;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import java.io.*;
import java.math.BigInteger;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.ReadableByteChannel;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;

/**
 * Created by cdutz on 11.05.2012.
 */
public abstract class BaseConverter {

    protected final Map<String, MavenArtifact> checksums = new HashMap<String, MavenArtifact>();

    protected static final String MAVEN_CENTRAL_SHA_1_QUERY_URL = "http://search.maven.org/solrsearch/select?rows=20&wt=json&q=1:";
    // Artifactory: "http://server:port/artifactory/api/search/checksum?repos=libs-release-local&md5=04040c7c184620af0a0a8a3682a75eb7
    // Nexus: "http://repository.sonatype.org/service/local/data_index?a=04040c7c184620af0a0a8a3682a75eb7"

    protected File rootSourceDirectory;
    protected File rootTargetDirectory;

    protected Configuration freemarkerConfig;

    protected BaseConverter(File rootSourceDirectory, File rootTargetDirectory) throws ConverterException {
        if(rootSourceDirectory == null) {
            throw new ConverterException("Air SDK directory is null.");
        }
        if(rootTargetDirectory == null) {
            throw new ConverterException("Target directory is null.");
        }

        this.rootSourceDirectory = rootSourceDirectory;
        this.rootTargetDirectory = rootTargetDirectory;

        this.freemarkerConfig = new Configuration(Configuration.VERSION_2_3_22);
        this.freemarkerConfig.setDefaultEncoding("UTF-8");
        this.freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
        this.freemarkerConfig.setClassForTemplateLoading(this.getClass(), "/");
    }

    public void convert() throws ConverterException {
        if(rootSourceDirectory.isFile()) {
            processArchive();
        } else {
            processDirectory();
        }
    }

    abstract protected void processDirectory() throws ConverterException;

    protected void processArchive() throws ConverterException {

    }

    protected String calculateChecksum(File jarFile) throws ConverterException {
        // Implement the calculation of checksums for a given jar.
        InputStream is = null;
        try {
            MessageDigest digest = MessageDigest.getInstance("SHA-1");

            is = new FileInputStream(jarFile);
            final byte[] buffer = new byte[8192];
            int read;
            try {
                while( (read = is.read(buffer)) > 0) {
                    digest.update(buffer, 0, read);
                }
                final byte[] md5sum = digest.digest();
                final BigInteger bigInt = new BigInteger(1, md5sum);
                return bigInt.toString(16);
            }
            catch(IOException e) {
                throw new ConverterException("Unable to process file for MD5", e);
            }
        } catch (NoSuchAlgorithmException e) {
            throw new ConverterException("Error calculating checksum of file '" + jarFile.getPath() + "'", e);
        } catch (FileNotFoundException e) {
            throw new ConverterException("Error calculating checksum of file '" + jarFile.getPath() + "'", e);
        } finally {
            if(is != null) {
                try {
                    is.close();
                } catch(IOException e) {
                    // Ignore ...
                }
            }
        }
    }

    protected MavenArtifact lookupMetadataForChecksum(String checksum) throws ConverterException {
        String output = null;
        try {
            final URL queryUrl = new URL(MAVEN_CENTRAL_SHA_1_QUERY_URL + checksum);

            URLConnection connection;
            ProxySettings proxySettings = ProxySettings.getProxySettings();
            if (proxySettings != null) {
                SocketAddress socketAddress = new InetSocketAddress(proxySettings.getHost(), proxySettings.getPort());
                Proxy proxy = new Proxy(Proxy.Type.valueOf(proxySettings.getProtocol().toUpperCase()), socketAddress);
                connection = queryUrl.openConnection(proxy);
            } else {
                connection = queryUrl.openConnection();
            }
            ReadableByteChannel rbc = null;
            try {
                rbc = Channels.newChannel(connection.getInputStream());
                final ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
                if (rbc.read(byteBuffer) > 0) {
                    output = new String(byteBuffer.array(), "UTF-8");
                }
            } finally {
                if(rbc != null) {
                    rbc.close();
                }
            }
        } catch (MalformedURLException e) {
            throw new ConverterException("Error querying maven central.", e);
        } catch (IOException e) {
            throw new ConverterException("Error querying maven central.", e);
        }

        if(output != null) {
            final BufferedReader reader = new BufferedReader(new StringReader(output));
            final StringBuilder builder = new StringBuilder();
            try {
                for (String line; (line = reader.readLine()) != null; ) {
                    builder.append(line).append("\n");
                }
                final JSONTokener tokener = new JSONTokener(builder.toString());
                final JSONObject rootObject = new JSONObject(tokener);

                final JSONObject responseObject = (JSONObject) rootObject.get("response");
                final int numFound = (Integer) responseObject.get("numFound");
                if (numFound == 0) {
                    return null;
                } else if (numFound == 1) {
                    final JSONArray docs = (JSONArray) responseObject.get("docs");
                    final JSONObject firstHit = (JSONObject) docs.get(0);

                    final MavenArtifact artifactMetadata = new MavenArtifact();
                    artifactMetadata.setGroupId((String) firstHit.get("g"));
                    artifactMetadata.setArtifactId((String) firstHit.get("a"));
                    artifactMetadata.setVersion((String) firstHit.get("v"));
                    artifactMetadata.setPackaging((String) firstHit.get("p"));

                    return artifactMetadata;
                } else {
                    long newestTimestamp = 0;
                    JSONObject newestVersion = null;

                    JSONArray options = (JSONArray) responseObject.get("docs");
                    // if the "groupId" is "batik" then use the newer version.
                    for (int i = 0; i < numFound; i++) {
                        final JSONObject option = (JSONObject) options.get(0);
                        if ("batik".equals(option.get("g")) && "batik-dom".equals(option.get("a")) && "jar".equals(option.get("p"))) {
                            final long timestamp = (Long) option.get("timestamp");
                            if (timestamp > newestTimestamp) {
                                newestTimestamp = timestamp;
                                newestVersion = option;
                            }
                        }
                    }

                    if (newestVersion != null) {
                        final MavenArtifact artifactMetadata = new MavenArtifact();
                        artifactMetadata.setGroupId((String) newestVersion.get("g"));
                        artifactMetadata.setArtifactId((String) newestVersion.get("a"));
                        artifactMetadata.setVersion((String) newestVersion.get("v"));
                        artifactMetadata.setPackaging((String) newestVersion.get("p"));

                        return artifactMetadata;
                    } else {
                        System.out.println("For jar-file with checksum: " + checksum +
                                " more than one result was returned by query: " +
                                MAVEN_CENTRAL_SHA_1_QUERY_URL + checksum);
                    }
                }
            } catch (IOException e) {
                throw new ConverterException("Error processing Metadata for checksum: '" + checksum + "'", e);
            } catch (JSONException e) {
                throw new ConverterException("Error processing Metadata for checksum: '" + checksum + "'", e);
            }
        }
        return null;
    }

    protected void copyFile(File source, File target) throws ConverterException {
        try {
            final File outputDirectory = target.getParentFile();
            if(!outputDirectory.exists()) {
                if(!outputDirectory.mkdirs()) {
                    throw new ConverterException("Could not create directory: " + outputDirectory.getAbsolutePath());
                }
            }

            final InputStream in = new FileInputStream(source);
            final OutputStream out = new FileOutputStream(target);

            final byte[] buf = new byte[1024];
            int len;
            while ((len = in.read(buf)) > 0){
                out.write(buf, 0, len);
            }

            in.close();
            out.close();
        } catch(IOException e) {
            throw new ConverterException("Error copying file from '" + source.getPath() +
                    "' to '" + target.getPath() + "'", e);
        }
    }

    protected void writePomArtifact(MavenArtifact pomData) throws ConverterException {
        final File outputFile = pomData.getPomTargetFile(rootTargetDirectory);
        createPomDocument(pomData, outputFile);
    }

    protected void createPomDocument(final MavenArtifact metadata, File outputFile) throws ConverterException {
        try {
            // Build a context to hold the model
            Map<String, Object> freemarkerContext = new HashMap<String, Object>();
            freemarkerContext.put("artifact", metadata);

            // Try to get a template "templates/{type}.vm".
            Template template;
            URL check = this.getClass().getClassLoader().getResource("templates/" + metadata.getPackaging() + ".ftl");
            if(check != null) {
                template = freemarkerConfig.getTemplate("templates/" + metadata.getPackaging() + ".ftl");
            } else {
                template = freemarkerConfig.getTemplate("templates/default.ftl");
            }

            // Prepare an output stream to which the output can be generated.
            FileWriter writer = null;
            try {
                if(!outputFile.getParentFile().exists()) {
                    if(!outputFile.getParentFile().mkdirs()) {
                        throw new ConverterException("Could not create template output directory.");
                    }
                }

                writer = new FileWriter(outputFile);

                // Have Freemarker generate the output for the template.
                template.process(freemarkerContext, writer);
            } finally {
                if(writer != null) {
                    writer.close();
                }
            }
        } catch (Exception e) {
            throw new ConverterException("Error generating template output.", e);
        }
    }

    protected void writeDummy(final File targetFile) throws ConverterException {
        try {
            final ZipOutputStream out = new ZipOutputStream(new FileOutputStream(targetFile));
            out.putNextEntry(new ZipEntry("dummy"));
            out.closeEntry();
            out.close();
        } catch (IOException e) {
            throw new ConverterException("Error generating dummy resouce bundle.");
        }
    }

    protected MavenArtifact resolveArtifact(File sourceFile, String defaultGroupId, String defaultVersion)
            throws ConverterException {
        // Calculate a checksum for the current file. We will use this checksum to query maven central
        // in order to find out if this lib has already been published. If it has, there is no need to
        // publish it again under a new name. In case a matching artifact is found the generated FDK
        // will use the already deployed version. Additionally the checksum will be saved and if a
        // fdk generated after this one uses the same version of a lib, the version of the older fdk is
        // used also reducing the amount of jars that have to be re-deployed.
        final String checksum = calculateChecksum(sourceFile);

        // Try to get artifact metadata based upon the checksum by looking up the internal cache.
        MavenArtifact artifact =  checksums.get(checksum);

        // Reusing artifact from other sdk version.
        if(artifact != null) {
            System.out.println("Reusing artifact (" + checksum + ") : " + artifact.getGroupId() + ":" +
                    artifact.getArtifactId() + ":" + artifact.getVersion());
            return artifact;
        }
        // Id no artifact was found in the local cache, continue processing.
        else {
            // Do a lookup in maven central.
            artifact = lookupMetadataForChecksum(checksum);

            // The file was available on maven central, so use that version instead of the one coming with the sdk.
            if(artifact != null) {
                System.out.println("Using artifact from Maven Central (" + checksum + ") : " +
                        artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getVersion());
            }
            // The file was not available on maven central, so we have to add it manually.
            else {
                // The artifact name is the name of the jar.
                final String artifactFileName = sourceFile.getName();
                final String dependencyArtifactId = artifactFileName.substring(0, artifactFileName.lastIndexOf("."));
                final String dependencyArtifactPackaging =
                        artifactFileName.substring(artifactFileName.lastIndexOf(".") + 1);

                // Generate a new metadata object
                artifact = new MavenArtifact();
                artifact.setGroupId(defaultGroupId);
                artifact.setArtifactId(dependencyArtifactId);
                artifact.setVersion(defaultVersion);
                artifact.setPackaging(dependencyArtifactPackaging);
                artifact.addDefaultBinaryArtifact(sourceFile);

                // Create the pom document that will reside next to the artifact lib.
                writeArtifact(artifact);
            }

            // Remember the checksum for later re-usage.
            checksums.put(checksum, artifact);

            return artifact;
        }
    }

    protected void writeArtifact(MavenArtifact artifact) throws ConverterException {
        // Write the pom itself.
        writePomArtifact(artifact);
        final List<String> binaryClassifiers = artifact.getBinaryFilesClassifiers();
        for(final String classifier : binaryClassifiers) {
            final File binarySourceFile = artifact.getBinarySourceFile(classifier);
            final File binaryTargetFile = artifact.getBinaryTargetFile(rootTargetDirectory, classifier);
            copyFile(binarySourceFile, binaryTargetFile);
        }
    }

    protected void generateZip(File[] sourceFiles, File targetFile) throws ConverterException {
        if((sourceFiles == null) || (sourceFiles.length == 0)) {
            return;
        }
        final File rootDir = sourceFiles[0].getParentFile();
        generateZip(rootDir, sourceFiles, targetFile);
    }

    protected void generateZip(File rootDir, File[] sourceFiles, File targetFile) throws ConverterException {
        if((sourceFiles == null) || (sourceFiles.length == 0)) {
            return;
        }
        final File zipInputFiles[] = new File[sourceFiles.length];
        System.arraycopy(sourceFiles, 0, zipInputFiles, 0, sourceFiles.length);

        try {
            // Add all the content to a zip-file.
            final ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream(targetFile));
            for (final File file : zipInputFiles) {
                addFileToZip(zipOutputStream, file, rootDir);
            }
            zipOutputStream.close();
        } catch(IOException e) {
            throw new ConverterException("Error generating " + targetFile.getName() + " zip.", e);
        }
    }

    protected void addFileToZip(ZipOutputStream zipOutputStream, File inputFile, File rootDirectory)
          throws ConverterException {

        if (inputFile == null) {
            return;
        }

        // If this is a directory, add all it's children.
        if (inputFile.isDirectory()) {
            final File directoryContent[] = inputFile.listFiles();
            if (directoryContent != null) {
                for (final File file : directoryContent) {
                    addFileToZip(zipOutputStream, file, rootDirectory);
                }
            }
        }
        // If this is a file, add it to the zips output.
        else {
            byte[] buf = new byte[1024];
            try {
                final FileInputStream in = new FileInputStream(inputFile);
                final String zipPath = inputFile.getAbsolutePath().substring(
                      rootDirectory.getAbsolutePath().length() + 1).replace("\\", "/");
                zipOutputStream.putNextEntry(new ZipEntry(zipPath));
                int len;
                while ((len = in.read(buf)) > 0) {
                    zipOutputStream.write(buf, 0, len);
                }
                zipOutputStream.closeEntry();
                in.close();
            } catch(IOException e) {
                throw new ConverterException("Error adding files to zip.", e);
            }
        }
    }

    /**
     * Get the version of an Flex SDK from the content of the SDK directory.
     *
     * @return version string for the current Flex SDK
     */
    protected String getFlexVersion(File rootDirectory) throws ConverterException {
        final File sdkDescriptor = new File(rootDirectory, "flex-sdk-description.xml");

        // If the descriptor is not present, return null as this FDK directory doesn't
        // seem to contain a Flex SDK.
        if(!sdkDescriptor.exists()) {
            return null;
        }

        final DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
        try {
            // Parse the document
            final DocumentBuilder db = dbf.newDocumentBuilder();
            final Document dom = db.parse(sdkDescriptor);

            // Get name, version and build nodes
            final Element root = dom.getDocumentElement();
            final String version = root.getElementsByTagName("version").item(0).getTextContent();
            final String build = root.getElementsByTagName("build").item(0).getTextContent();

            // In general the version consists of the content of the version element with an appended build-number.
            return (build.equals("0")) ? version + "-SNAPSHOT" : version;
        } catch (ParserConfigurationException pce) {
            throw new ConverterException("Error parsing flex-sdk-description.xml", pce);
        } catch (SAXException se) {
            throw new ConverterException("Error parsing flex-sdk-description.xml", se);
        } catch (IOException ioe) {
            throw new ConverterException("Error parsing flex-sdk-description.xml", ioe);
        }
    }

    protected Collection<File> listAllFiles(File source, FileFilter filter) {
        if(filter.accept(source)) {
            return Collections.singleton(source);
        }
        else if(source.isDirectory()) {
            File[] dirContent = source.listFiles();
            if(dirContent != null) {
                Collection<File> filteredContent = new LinkedList<File>();
                for(File child : dirContent) {
                    filteredContent.addAll(listAllFiles(child, filter));
                }
                return filteredContent;
            }
        }
        return Collections.emptyList();
    }

}
