/*
 * Copyright 2009-2012 by The Regents of the University of California
 * Licensed 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 from
 * 
 *     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 edu.uci.ics.asterix.installer.driver;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileFilter;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;
import java.util.Properties;
import java.util.Random;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

import org.apache.commons.io.IOUtils;

import edu.uci.ics.asterix.event.driver.EventDriver;
import edu.uci.ics.asterix.event.management.EventrixClient;
import edu.uci.ics.asterix.event.schema.cluster.Cluster;
import edu.uci.ics.asterix.event.schema.cluster.Node;
import edu.uci.ics.asterix.installer.error.InstallerException;
import edu.uci.ics.asterix.installer.error.OutputHandler;
import edu.uci.ics.asterix.installer.model.AsterixInstance;
import edu.uci.ics.asterix.installer.model.AsterixInstance.State;
import edu.uci.ics.asterix.installer.service.ServiceProvider;

public class InstallerUtil {

    public static AsterixInstance createAsterixInstance(String asterixInstanceName, Cluster cluster)
            throws FileNotFoundException, IOException {
        Properties asterixConfProp = new Properties();
        asterixConfProp.put("output_dir", cluster.getWorkingDir().getDir() + File.separator + "asterix_output");
        Node metadataNode = getMetadataNode(cluster);
        String asterixZipName = InstallerDriver.getAsterixZip().substring(
                InstallerDriver.getAsterixZip().lastIndexOf(File.separator) + 1);
        String asterixVersion = asterixZipName.substring("asterix-server-".length(),
                asterixZipName.indexOf("-binary-assembly"));
        AsterixInstance instance = new AsterixInstance(asterixInstanceName, cluster, asterixConfProp,
                metadataNode.getId(), asterixVersion);
        return instance;
    }

    public static void createAsterixZip(AsterixInstance asterixInstance, boolean newDeployment) throws IOException {
        writeAsterixConfigurationFile(asterixInstance, newDeployment);
        String asterixInstanceDir = InstallerDriver.getAsterixDir() + File.separator + asterixInstance.getName();
        unzip(InstallerDriver.getAsterixZip(), asterixInstanceDir);
        File sourceJar = new File(asterixInstanceDir + File.separator + "lib" + File.separator + "asterix-app-"
                + asterixInstance.getAsterixVersion() + ".jar");
        String origFile = "test.properties";
        File replacementFile = new File(asterixInstanceDir + File.separator + "test.properties");
        replaceInJar(sourceJar, origFile, replacementFile);
        new File(asterixInstanceDir + File.separator + "test.properties").delete();
        String asterixZipName = InstallerDriver.getAsterixZip().substring(
                InstallerDriver.getAsterixZip().lastIndexOf(File.separator) + 1);
        zipDir(new File(asterixInstanceDir), new File(asterixInstanceDir + File.separator + asterixZipName));

    }

    public static void addLibraryToAsterixZip(AsterixInstance asterixInstance, String dataverseName,
            String libraryName, String libraryPath) throws IOException {
        File instanceDir = new File(InstallerDriver.getAsterixDir() + File.separator + asterixInstance.getName());
        if (!instanceDir.exists()) {
            instanceDir.mkdirs();
        }
        String asterixZipName = InstallerDriver.getAsterixZip().substring(
                InstallerDriver.getAsterixZip().lastIndexOf(File.separator) + 1);

        String sourceZip = instanceDir.getAbsolutePath() + File.separator + asterixZipName;
        unzip(sourceZip, instanceDir.getAbsolutePath());
        File libraryPathInZip = new File(instanceDir.getAbsolutePath() + File.separator + "external" + File.separator
                + "library" + dataverseName + File.separator + "to-add" + File.separator + libraryName);
        libraryPathInZip.mkdirs();
        Runtime.getRuntime().exec("cp" + " " + libraryPath + " " + libraryPathInZip.getAbsolutePath());
        Runtime.getRuntime().exec("rm " + sourceZip);
        String destZip = InstallerDriver.getAsterixDir() + File.separator + asterixInstance.getName() + File.separator
                + asterixZipName;
        zipDir(instanceDir, new File(destZip));
        Runtime.getRuntime().exec("mv" + " " + destZip + " " + sourceZip);
    }

    private static Node getMetadataNode(Cluster cluster) {
        Random random = new Random();
        int nNodes = cluster.getNode().size();
        return cluster.getNode().get(random.nextInt(nNodes));
    }

    public static String getNodeDirectories(String asterixInstanceName, Node node, Cluster cluster) {
        String storeDataSubDir = asterixInstanceName + File.separator + "data" + File.separator;
        String storeLibrarySubDir = asterixInstanceName + File.separator + "library" + File.separator;
        String[] storeDirs = null;
        StringBuffer nodeDataStore = new StringBuffer();
        String storeDirValue = node.getStore();
        if (storeDirValue == null) {
            storeDirValue = cluster.getStore();
            if (storeDirValue == null) {
                throw new IllegalStateException(" Store not defined for node " + node.getId());
            }
            storeDataSubDir = node.getId() + File.separator + storeDataSubDir;
            storeLibrarySubDir = node.getId() + File.separator + storeLibrarySubDir;
        }

        storeDirs = storeDirValue.split(",");
        for (String ns : storeDirs) {
            nodeDataStore.append(ns + File.separator + storeDataSubDir.trim());
            nodeDataStore.append(",");
        }
        nodeDataStore.deleteCharAt(nodeDataStore.length() - 1);
        return nodeDataStore.toString();
    }

    private static void writeAsterixConfigurationFile(AsterixInstance asterixInstance, boolean newData)
            throws IOException {
        String asterixInstanceName = asterixInstance.getName();
        Cluster cluster = asterixInstance.getCluster();
        String metadataNodeId = asterixInstance.getMetadataNodeId();

        StringBuffer conf = new StringBuffer();
        conf.append("MetadataNode=" + asterixInstanceName + "_" + metadataNodeId + "\n");
        conf.append("NewUniverse=" + newData + "\n");

        for (Node node : cluster.getNode()) {
            String nodeDir = getNodeDirectories(asterixInstance.getName(), node, cluster);
            conf.append(asterixInstanceName + "_" + node.getId() + ".stores" + "=" + nodeDir + "\n");
        }
        Properties asterixConfProp = asterixInstance.getConfiguration();
        String outputDir = asterixConfProp.getProperty("output_dir");
        conf.append("OutputDir=" + outputDir);
        File asterixConfDir = new File(InstallerDriver.getAsterixDir() + File.separator + asterixInstanceName);
        asterixConfDir.mkdirs();
        dumpToFile(InstallerDriver.getAsterixDir() + File.separator + asterixInstanceName + File.separator
                + "test.properties", conf.toString());
    }

    public static Properties getAsterixConfiguration(String asterixConf) throws FileNotFoundException, IOException {
        Properties prop = new Properties();
        prop.load(new FileInputStream(asterixConf));
        return prop;
    }

    public static void unzip(String sourceFile, String destDir) throws IOException {
        BufferedOutputStream dest = null;
        FileInputStream fis = new FileInputStream(sourceFile);
        ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
        ZipEntry entry = null;

        int BUFFER_SIZE = 4096;
        while ((entry = zis.getNextEntry()) != null) {
            String dst = destDir + File.separator + entry.getName();
            if (entry.isDirectory()) {
                createDir(destDir, entry);
                continue;
            }
            int count;
            byte data[] = new byte[BUFFER_SIZE];

            //write the file to the disk
            FileOutputStream fos = new FileOutputStream(dst);
            dest = new BufferedOutputStream(fos, BUFFER_SIZE);
            while ((count = zis.read(data, 0, BUFFER_SIZE)) != -1) {
                dest.write(data, 0, count);
            }
            //close the output streams
            dest.flush();
            dest.close();
        }

        zis.close();
    }

    public static void zipDir(File sourceDir, File destFile) throws IOException {
        FileOutputStream fos = new FileOutputStream(destFile);
        ZipOutputStream zos = new ZipOutputStream(fos);
        zipDir(sourceDir, destFile, zos);
        zos.close();
    }

    private static void zipDir(File sourceDir, final File destFile, ZipOutputStream zos) throws IOException {
        File[] dirList = sourceDir.listFiles(new FileFilter() {
            public boolean accept(File f) {
                return !f.getName().endsWith(destFile.getName());
            }
        });
        for (int i = 0; i < dirList.length; i++) {
            File f = dirList[i];
            if (f.isDirectory()) {
                zipDir(f, destFile, zos);
            } else {
                int bytesIn = 0;
                byte[] readBuffer = new byte[2156];
                FileInputStream fis = new FileInputStream(f);
                ZipEntry entry = new ZipEntry(sourceDir.getName() + File.separator + f.getName());
                zos.putNextEntry(entry);
                while ((bytesIn = fis.read(readBuffer)) != -1) {
                    zos.write(readBuffer, 0, bytesIn);
                }
                fis.close();
            }
        }
    }

    private static void replaceInJar(File sourceJar, String origFile, File replacementFile) throws IOException {
        File destJar = new File(sourceJar.getAbsolutePath() + ".modified");
        InputStream jarIs = null;
        FileInputStream fis = new FileInputStream(replacementFile);
        JarFile sourceJarFile = new JarFile(sourceJar);
        Enumeration<JarEntry> entries = sourceJarFile.entries();
        JarOutputStream jos = new JarOutputStream(new FileOutputStream(destJar));
        byte[] buffer = new byte[2048];
        int read;
        while (entries.hasMoreElements()) {
            JarEntry entry = (JarEntry) entries.nextElement();
            String name = entry.getName();
            if (name.equals(origFile)) {
                continue;
            }
            jarIs = sourceJarFile.getInputStream(entry);
            jos.putNextEntry(entry);
            while ((read = jarIs.read(buffer)) != -1) {
                jos.write(buffer, 0, read);
            }
        }
        JarEntry entry = new JarEntry(origFile);
        jos.putNextEntry(entry);
        while ((read = fis.read(buffer)) != -1) {
            jos.write(buffer, 0, read);
        }
        fis.close();
        jos.close();
        jarIs.close();
        sourceJar.delete();
        destJar.renameTo(sourceJar);
        sourceJar.setExecutable(true);
    }

    public static void dumpToFile(String dest, String content) throws IOException {
        FileWriter writer = new FileWriter(dest);
        writer.write(content);
        writer.close();
    }

    private static void createDir(String destDirectory, ZipEntry entry) {
        String name = entry.getName();
        int index = name.lastIndexOf(File.separator);
        String dirSequence = name.substring(0, index);
        File newDirs = new File(destDirectory + File.separator + dirSequence);
        newDirs.mkdirs();
    }

    public static AsterixInstance validateAsterixInstanceExists(String name, State... permissibleStates)
            throws Exception {
        AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService().getAsterixInstance(name);
        if (instance == null) {
            throw new InstallerException("Asterix instance by name " + name + " does not exist.");
        }
        boolean valid = false;
        for (State state : permissibleStates) {
            if (state.equals(instance.getState())) {
                valid = true;
                break;
            }
        }
        if (!valid) {
            throw new InstallerException("Asterix instance by the name " + name + " is in " + instance.getState()
                    + " state ");
        }
        return instance;
    }

    public static void validateAsterixInstanceNotExists(String name) throws Exception {
        AsterixInstance instance = ServiceProvider.INSTANCE.getLookupService().getAsterixInstance(name);
        if (instance != null) {
            throw new InstallerException("Asterix instance by name " + name + " already exists.");
        }
    }

    public static void evaluateConflictWithOtherInstances(AsterixInstance instance) throws Exception {
        List<AsterixInstance> existingInstances = ServiceProvider.INSTANCE.getLookupService().getAsterixInstances();
        List<String> usedIps = new ArrayList<String>();
        String masterIp = instance.getCluster().getMasterNode().getIp();
        for (Node node : instance.getCluster().getNode()) {
            usedIps.add(node.getIp());
        }
        usedIps.add(instance.getCluster().getMasterNode().getIp());
        boolean conflictFound = false;
        AsterixInstance conflictingInstance = null;
        for (AsterixInstance existing : existingInstances) {
            conflictFound = existing.getCluster().getMasterNode().getIp().equals(masterIp);
            if (conflictFound) {
                conflictingInstance = existing;
                break;
            }
            for (Node n : existing.getCluster().getNode()) {
                if (usedIps.contains(n.getIp())) {
                    conflictFound = true;
                    conflictingInstance = existing;
                    break;
                }
            }
        }
        if (conflictFound) {
            throw new Exception("Cluster definition conflicts with an existing instance of Asterix: "
                    + conflictingInstance.getName());
        }
    }

    public static void deleteDirectory(String path) throws IOException {
        Runtime.getRuntime().exec("rm -rf " + path);
    }

    public static String executeLocalScript(String path, List<String> args) throws Exception {
        List<String> pargs = new ArrayList<String>();
        pargs.add("/bin/bash");
        pargs.add(path);
        if (args != null) {
            pargs.addAll(args);
        }
        ProcessBuilder pb = new ProcessBuilder(pargs);
        pb.environment().putAll(EventDriver.getEnvironment());
        pb.environment().put("IP_LOCATION", EventDriver.CLIENT_NODE.getIp());
        Process p = pb.start();
        BufferedInputStream bis = new BufferedInputStream(p.getInputStream());
        StringWriter writer = new StringWriter();
        IOUtils.copy(bis, writer, "UTF-8");
        return writer.toString();
    }

    public static EventrixClient getEventrixClient(Cluster cluster) throws Exception {
        return new EventrixClient(
                InstallerDriver.getManagixHome() + File.separator + InstallerDriver.MANAGIX_EVENT_DIR, cluster, false,
                OutputHandler.INSTANCE);
    }

}
