/*
 * 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.tomcat.jakartaee;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.concurrent.TimeUnit;
import java.util.jar.Attributes;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarInputStream;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.apache.commons.io.input.CloseShieldInputStream;
import org.apache.commons.io.output.CloseShieldOutputStream;

public class Migration {

    private static final Logger logger = Logger.getLogger(Migration.class.getCanonicalName());
    private static final StringManager sm = StringManager.getManager(Migration.class);

    private EESpecProfile profile = EESpecProfile.TOMCAT;
    private File source;
    private File destination;
    private final List<Converter> converters;

    public Migration() {
        // Initialise the converters
        converters = new ArrayList<>();

        converters.add(new TextConverter());
        converters.add(new ClassConverter());

        // Final converter is the pass-through converter
        converters.add(new PassThroughConverter());
    }

    /**
     * Set the Jakarta EE specifications that should be used.
     *
     * @param profile the Jakarta EE specification profile
     */
    public void setEESpecProfile(EESpecProfile profile) {
        this.profile = profile;
    }

    /**
     * Get the Jakarta EE profile being used.
     *
     * @return the profile
     */
    public EESpecProfile getEESpecProfile() {
        return profile;
    }

    public void setSource(File source) {
        if (!source.canRead()) {
            throw new IllegalArgumentException(sm.getString("migration.cannotReadSource",
                    source.getAbsolutePath()));
        }
        this.source = source;
    }


    public void setDestination(File destination) {
        this.destination = destination;
    }


    public boolean execute() throws IOException {
        logger.log(Level.INFO, sm.getString("migration.execute", source.getAbsolutePath(),
                destination.getAbsolutePath(), profile.toString()));
        boolean result = true;
        long t1 = System.nanoTime();
        if (source.isDirectory()) {
            if (destination.mkdirs()) {
                result = result && migrateDirectory(source, destination);
            } else {
                logger.log(Level.WARNING, sm.getString("migration.mkdirError", destination.getAbsolutePath()));
                result = false;
            }
        } else {
            // Single file
            File parentDestination = destination.getAbsoluteFile().getParentFile();
            if (parentDestination.exists() || parentDestination.mkdirs()) {
                result = result && migrateFile(source, destination);
            } else {
                logger.log(Level.WARNING, sm.getString("migration.mkdirError", parentDestination.getAbsolutePath()));
                result = false;
            }
        }
        logger.log(Level.INFO, sm.getString("migration.done",
                Long.valueOf(TimeUnit.MILLISECONDS.convert(System.nanoTime() - t1, TimeUnit.NANOSECONDS)),
                Boolean.valueOf(result)));
        return result;
    }


    private boolean migrateDirectory(File src, File dest) throws IOException {
        boolean result = true;
        String[] files = src.list();
        for (String file : files) {
            File srcFile = new File(src, file);
            File destFile = new File(dest, file);
            if (srcFile.isDirectory()) {
                if (destFile.mkdir()) {
                    result = result && migrateDirectory(srcFile, destFile);
                } else {
                    logger.log(Level.WARNING, sm.getString("migration.mkdirError", destFile.getAbsolutePath()));
                    result = false;
                }
            } else {
                result = result && migrateFile(srcFile, destFile);
            }
        }
        return result;
    }


    private boolean migrateFile(File src, File dest) throws IOException {
        boolean result = false;

        boolean inplace = src.equals(dest);
        if (!inplace) {
            try (InputStream is = new FileInputStream(src);
                 OutputStream os = new FileOutputStream(dest)) {
                result = migrateStream(src.getName(), is, os);
            }
        } else {
            ByteArrayOutputStream buffer = new ByteArrayOutputStream((int) (src.length() * 1.05));

            try (InputStream is = new FileInputStream(src)) {
                result = migrateStream(src.getName(), is, buffer);
            }

            try (OutputStream os = new FileOutputStream(dest)) {
                os.write(buffer.toByteArray());
            }
        }

        return result;
    }


    private boolean migrateArchive(InputStream src, OutputStream dest) throws IOException {
        boolean result = true;
        try (JarInputStream jarIs = new JarInputStream(new CloseShieldInputStream(src));
                JarOutputStream jarOs = new JarOutputStream(new CloseShieldOutputStream(dest))) {
            Manifest manifest = jarIs.getManifest();
            if (manifest != null) {
                // Make a safe copy to leave original manifest untouched.
                // Otherwise messing with signatures will fail
                manifest = new Manifest(manifest);
                updateVersion(manifest);
                if (removeSignatures(manifest)) {
                    logger.log(Level.WARNING, sm.getString("migration.warnSignatureRemoval"));
                }
                JarEntry manifestEntry = new JarEntry(JarFile.MANIFEST_NAME);
                jarOs.putNextEntry(manifestEntry);
                manifest.write(jarOs);
            }
            JarEntry jarEntry;
            while ((jarEntry = jarIs.getNextJarEntry()) != null) {
                String sourceName = jarEntry.getName();
                logger.log(Level.FINE, sm.getString("migration.entry", sourceName));
                if (isSignatureFile(sourceName)) {
                    logger.log(Level.FINE, sm.getString("migration.skipSignatureFile", sourceName));
                    continue;
                }
                String destName = profile.convert(sourceName);
                JarEntry destEntry = new JarEntry(destName);
                jarOs.putNextEntry(destEntry);
                result = result && migrateStream(destEntry.getName(), jarIs, jarOs);
            }
        }
        return result;
    }


    private boolean isSignatureFile(String sourceName) {
        return sourceName.startsWith("META-INF/")
                && (sourceName.endsWith(".SF") || sourceName.endsWith(".RSA") || sourceName.endsWith(".DSA") || sourceName.endsWith(".EC"));
    }


    private boolean migrateStream(String name, InputStream src, OutputStream dest) throws IOException {
        if (isArchive(name)) {
            logger.log(Level.INFO, sm.getString("migration.archive", name));
            return migrateArchive(src, dest);
        } else {
            logger.log(Level.FINE, sm.getString("migration.stream", name));
            for (Converter converter : converters) {
                if (converter.accepts(name)) {
                    converter.convert(src, dest, profile);
                    break;
                }
            }
            return true;
        }
    }


    private boolean removeSignatures(Manifest manifest) {
        boolean removedSignatures = manifest.getMainAttributes().remove(Attributes.Name.SIGNATURE_VERSION) != null;
        List<String> signatureEntries = new ArrayList<>();
        Map<String, Attributes> manifestAttributeEntries = manifest.getEntries();
        for (Entry<String, Attributes> entry : manifestAttributeEntries.entrySet()) {
            if (isCryptoSignatureEntry(entry.getValue())) {
                String entryName = entry.getKey();
                signatureEntries.add(entryName);
                logger.log(Level.FINE, sm.getString("migration.removeSignature", entryName));
                removedSignatures = true;
            }
        }

        for (String entry : signatureEntries) {
            manifestAttributeEntries.remove(entry);
        }

        return removedSignatures;
    }


    private boolean isCryptoSignatureEntry(Attributes attributes) {
        for (Object attributeKey : attributes.keySet()) {
            if (attributeKey.toString().endsWith("-Digest")) {
                return true;
            }
        }
        return false;
    }


    private void updateVersion(Manifest manifest) {
        updateVersion(manifest.getMainAttributes());
        for (Attributes attributes : manifest.getEntries().values()) {
            updateVersion(attributes);
        }
    }


    private void updateVersion(Attributes attributes) {
        if (attributes.containsKey(Attributes.Name.IMPLEMENTATION_VERSION)) {
            String newValue = attributes.get(Attributes.Name.IMPLEMENTATION_VERSION) + "-" + Info.getVersion();
            attributes.put(Attributes.Name.IMPLEMENTATION_VERSION, newValue);
        }
    }

    private static boolean isArchive(String fileName) {
        return fileName.endsWith(".jar") || fileName.endsWith(".war") || fileName.endsWith(".zip");
    }
}
