/*
 * 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.ace.client.repository.helper.base;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.Writer;
import java.lang.ref.Reference;
import java.lang.ref.WeakReference;
import java.net.URL;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Arrays;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.ace.client.repository.helper.PropertyResolver;
import org.apache.ace.client.repository.helper.configuration.ConfigurationHelper;
import org.apache.ace.connectionfactory.ConnectionFactory;
import org.apache.velocity.VelocityContext;
import org.apache.velocity.app.Velocity;

import aQute.bnd.annotation.ConsumerType;

/**
 * This class can be used as a 'default' artifact preprocessor, using the Velocity template engine to preprocess
 * the artifact.
 */
@ConsumerType
public class VelocityArtifactPreprocessor extends ArtifactPreprocessorBase {

    // matches a valid OSGi version
    private final Pattern VERSION_PATTERN = Pattern.compile("(\\d+)(\\.(\\d+)(\\.(\\d+)([\\.-]([\\w-]+))?)?)?");

    private static Object m_initLock = new Object();
    private static boolean m_velocityInitialized = false;

    private final Map<String, Reference<byte[]>> m_cachedArtifacts;
    private final Map<String, Reference<String>> m_cachedHashes;
    private final MessageDigest m_md5;

    /**
     * Creates a new {@link VelocityArtifactPreprocessor} instance.
     * @param connectionFactory 
     */
    public VelocityArtifactPreprocessor(ConnectionFactory connectionFactory) {
        super(connectionFactory);
        try {
            m_md5 = MessageDigest.getInstance("MD5");
        }
        catch (NoSuchAlgorithmException e) {
            throw new RuntimeException("Failed to create VelocityArtifactPreprocessor instance!", e);
        }

        m_cachedArtifacts = new ConcurrentHashMap<String, Reference<byte[]>>();
        m_cachedHashes = new ConcurrentHashMap<String, Reference<String>>();
    }

    @Override
    public boolean needsNewVersion(String url, PropertyResolver props, String targetID, String fromVersion) {

        byte[] input = null;
        byte[] result = null;
        try {
            init();
            input = getArtifactAsBytes(url);
            result = process(input, props);
        }
        catch (IOException ioe) {
            // problem initializing velocity, or we cannot retrieve the 
            // original artifact, or process it; we can't say anything now.
            return true;
        }

        // first check: did we need any processing at all?
        if (Arrays.equals(result, input)) {
            return false;
        }

        // hash the processed template
        String newHash = hash(result);

        // find the hash for the previous version
        String oldHash = getHashForVersion(url, targetID, fromVersion);

        // Note: we do not cache any previously created processed templates, since the call that asks us to approve a new version
        // may cross a pending needsNewVersion call.
        boolean answer = !newHash.equals(oldHash);
        return answer;
    }

    @Override
    public String preprocess(String url, PropertyResolver props, String targetID, String version, URL obrBase) throws IOException {
        init();

        // first, get the original data.
        byte[] input = getArtifactAsBytes(url);
        // process the template
        byte[] result = process(input, props);

        // first check: did we need any processing at all?
        if (Arrays.equals(result, input)) {
            // template isn't modified; use direct URL instead...
            return url;
        }
        setHashForVersion(url, targetID, version, hash(result));
        String name = getFilename(url, targetID, version);

        String location = null;
        if(obrBase.getProtocol().equals("http")){
            // upload the new resource to the OBR
            location = upload(new ByteArrayInputStream(result), name, ConfigurationHelper.MIMETYPE, obrBase);
        } else {
            // this is only to support the unit tests
            location = obrBase + name;
        }
        return location;
    }

    /**
     * Initializes this preprocessor by making sure {@link Velocity#init()} is called.
     * <p>This method may be called multiple times.</p>
     * 
     * @throws IOException in case of problems initializing Velocity.
     */
    private void init() throws IOException {
        if (m_velocityInitialized) {
            return;
        }
        else {
            synchronized (m_initLock) {
                if (!m_velocityInitialized) {
                    try {
                        Velocity.init();
                        m_velocityInitialized = true;
                    }
                    catch (Exception e) {
                        // Something went seriously bad initializing velocity.
                        throw new IOException("Error initializing Velocity: " + e.getMessage());
                    }
                }
            }
        }
    }

    /**
     * Creates a new filename for a processed template.
     * 
     * @param url the original url
     * @param targetID the targetID
     * @param version the version
     * @return a new filename
     */
    private String getFilename(String url, String targetID, String targetVersion) {

        String fileName = "";
        String fileExtension = "";
        String fileVersion = "";
        
        int indexOfLastSlash = url.lastIndexOf('/');
        if (indexOfLastSlash != -1) {
            fileName = url.substring(indexOfLastSlash + 1);
        }
        int indexOfLastDot = fileName.lastIndexOf('.');
        if (indexOfLastDot != -1) {
            fileExtension = fileName.substring(indexOfLastDot);
            fileName = fileName.substring(0, indexOfLastDot);
        }

        int dashIndex = fileName.indexOf('-');
        while (dashIndex != -1 && fileVersion.equals("")) {
            String versionCandidate = fileName.substring(dashIndex + 1);
            Matcher versionMatcher = VERSION_PATTERN.matcher(versionCandidate);
            if(versionMatcher.matches()){
                fileName = fileName.substring(0, dashIndex);
                fileVersion = versionCandidate;
            } else {
                dashIndex = fileName.indexOf(fileName, dashIndex);                
            }
        }

        fileName = fileName + ".target-" + targetID + "-" + targetVersion + fileExtension;
        return fileName;
    }

    /**
     * Creates a hash for caching.
     * 
     * @param url the url
     * @param target the target
     * @param version the version
     * @return a hash
     */
    private String getHashForVersion(String url, String target, String version) {
        String key = createHashKey(url, target, version);
        Reference<String> ref = m_cachedHashes.get(key);
        String hash = (ref != null) ? ref.get() : null;
        return hash;
    }

    /**
     * Adds a hash to the cache.
     * 
     * @param url the url
     * @param target the target
     * @param version the version
     * @param hash the hash
     */
    private void setHashForVersion(String url, String target, String version, String hash) {
        String key = createHashKey(url, target, version);
        m_cachedHashes.put(key, new WeakReference<String>(hash));
    }

    /**
     * Applies the template processor to the given byte array.
     * 
     * @param input the template (as byte array) to process;
     * @param props the {@link PropertyResolver} to use.
     * @return the processed template, never <code>null</code>.
     * @throws IOException in case of I/O problems.
     */
    private byte[] process(byte[] input, PropertyResolver props) throws IOException {
        VelocityContext context = new VelocityContext();
        context.put("context", props);
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            Writer writer = new OutputStreamWriter(baos);
            Velocity.evaluate(context, writer, "", new InputStreamReader(new ByteArrayInputStream(input)));
            writer.flush();
            return baos.toByteArray();
        }
        catch (IOException ioe) {
            throw new IOException("Error processing the artifact: " + ioe.getMessage());
        }
    }

    /**
     * Reads all information from a given URL, and returns that as a byte array. The byte array is not to be changed, and could be potentially come from a cache.
     * 
     * @param url the URL to read the artifact from, cannot be <code>null</code>.
     * @return the read (or cached) bytes, can be <code>null</code>.
     * @throws IOException in case of I/O problems.
     */
    private byte[] getArtifactAsBytes(String url) throws IOException {
        byte[] result = null;
        Reference<byte[]> ref = m_cachedArtifacts.get(url);
        if (ref == null || ((result = ref.get()) == null)) {
            result = getBytesFromUrl(url);
        }
        return result;
    }

    /**
     * Reads all bytes from the given URL and caches its result.
     * 
     * @param url the URL to read the bytes for, cannot be <code>null</code>.
     * @return the read bytes from the given URL, can be <code>null</code> if the reading failed.
     * @throws IOException in case of I/O problems.
     */
    private byte[] getBytesFromUrl(String url) throws IOException {
        byte[] result = null;

        // ACE-267
        InputStream in = m_connectionFactory.createConnection(new URL(url)).getInputStream();
        try {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buf = new byte[BUFFER_SIZE];
            for (int count = in.read(buf); count != -1; count = in.read(buf)) {
                baos.write(buf, 0, count);
            }
            result = baos.toByteArray();
            m_cachedArtifacts.put(url, new WeakReference<byte[]>(result));
        }
        finally {
            silentlyClose(in);
        }
        return result;
    }

    /**
     * Creates a key for storing/retrieving a hash.
     * 
     * @param url
     * @param target
     * @param version
     * @return a hash key, never <code>null</code>.
     */
    private String createHashKey(String url, String target, String version) {
        return new StringBuilder().append('[')
            .append(url)
            .append("][")
            .append(target)
            .append("][")
            .append(version)
            .append(']').toString();
    }

    /**
     * Computes a hash for a given byte array.
     * 
     * @param input the byte array to compute the hash for.
     * @return a hash for the given byte array, never <code>null</code>.
     */
    private String hash(byte[] input) {
        return new String(m_md5.digest(input));
    }
}
