/*******************************************************************************
 * Copyright (c) 2010-2014, Abel Hegedus, Istvan Rath and Daniel Varro
 * This program and the accompanying materials are made available under the
 * terms of the Eclipse Public License v. 2.0 which is available at
 * http://www.eclipse.org/legal/epl-v20.html.
 * 
 * SPDX-License-Identifier: EPL-2.0
 *******************************************************************************/
package org.eclipse.viatra.modelobfuscator.application.common;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.TimeUnit;

import org.eclipse.emf.common.util.URI;
import org.eclipse.emf.ecore.EObject;
import org.eclipse.emf.ecore.EPackage;
import org.eclipse.emf.ecore.resource.Resource;
import org.eclipse.emf.ecore.resource.impl.ResourceSetImpl;
import org.eclipse.emf.ecore.util.BasicExtendedMetaData;
import org.eclipse.emf.ecore.util.ExtendedMetaData;
import org.eclipse.emf.ecore.xmi.XMLResource;
import org.eclipse.emf.ecore.xmi.impl.EcoreResourceFactoryImpl;
import org.eclipse.equinox.app.IApplication;
import org.eclipse.viatra.modelobfuscator.emf.simple.AbstractModelObfuscator;
import org.eclipse.viatra.modelobfuscator.emf.simple.EMFModelObfuscatorBuilder;
import org.eclipse.viatra.modelobfuscator.xml.XMLModelObfuscator;
import org.eclipse.viatra.modelobfuscator.xml.XMLModelObfuscatorBuilder;
import org.eclipse.viatra.modelobfuscator.xml.XMLSchemaConfiguration;

import com.google.common.base.Optional;
import com.google.common.base.Stopwatch;
import com.google.common.base.Strings;
import com.google.common.collect.HashMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;

/**
 * @author Abel Hegedus
 *
 */
public class ModelObfuscatorHeadless {

    /*
     * Command line parameters 
     */
    private static String configParam = "-c";
    private static String configLongParam = "--config";
    private static String seedParam   = "-s";
    private static String saltParam   = "--salt";

    /*
     * Property keys
     */
    private static final String PROPERTY_PREFIX = "org.eclipse.viatra.modelobfuscator/";
    private static final String OBFUSCATION_MODE_PROPERTY = PROPERTY_PREFIX + "mode";
    private static final String XML_OBFUSCATION_MODE = "xml";
    private static final String EMF_OBFUSCATION_MODE= "emf";
    private static final String OBFUSCATION_INPUT_PROPERTY = PROPERTY_PREFIX + "input";
    private static final String OBFUSCATION_OUTPUT_PROPERTY = PROPERTY_PREFIX + "output";
    private static final String OBFUSCATION_ECORE_PROPERTY = PROPERTY_PREFIX + "ecore";
    private static final String OBFUSCATION_TAGS_PROPERTY = PROPERTY_PREFIX + "tags";
    private static final String OBFUSCATION_ATTRIBUTES_PROPERTY = PROPERTY_PREFIX + "attributes";

    /**
     * @param args
     * @return
     */
    public Integer performHeadlessObfuscation(String[] args) {
        String config = null;
        String seed = null;
        String salt = null;
        
        if (args == null || args.length == 0) {
            reportError("Configuration parameter not set");
        }
        int i = 0;
        
        while (i < args.length) {
           if (args[i].equals(configLongParam)) {
               config = args[i + 1];
                i += 2;
            } else if (args[i].equals(configParam)) {
                config = args[i + 1];
                i += 2;
            } else if (args[i].equals(seedParam)) {
                seed = args[i + 1];
                i += 2;
            } else if (args[i].equals(saltParam)) {
                salt = args[i + 1];
                i += 2;
            } else {
                i++;
            }
        }

        System.out.println("Obfuscation called with:\n"
                + "  Config : " + Strings.nullToEmpty(config) + "\n"
                + "  Seed   : " + Strings.nullToEmpty(seed) + "\n"
                + "  Salt   : " + Strings.nullToEmpty(salt));
        
        if (config == null) {
            reportError("Configuration parameter not set");
        }

        Properties configuration = null;
        // load configuration file
        try {
            configuration = loadConfigurationPropertyFile(config);
        } catch (FileNotFoundException e) {
            reportError("Could not find configuration file");
        } catch (IOException e) {
            reportError("Could not read configuration file");
        }

        String mode = getPropertyValue(configuration, OBFUSCATION_MODE_PROPERTY);
        
        if(mode.equals(EMF_OBFUSCATION_MODE)) {
            
            performEMFObfuscation(seed, salt, configuration);
            
        } else if(mode.equals(XML_OBFUSCATION_MODE)) {

            performXMLObfuscation(seed, salt, configuration);
            
        } else {
            reportError("Unknown mode " + mode + " selected in configuration");
        }
        
        return IApplication.EXIT_OK;
    }

    /**
     * @param seed
     * @param salt
     * @param configuration
     */
    private void performEMFObfuscation(String seed, String salt, Properties configuration) {
        // ensure output directory existence
        File outputDirectory = checkOutputDirectory(configuration);
        
        // check input file existence
        Map<String, URI> inputs = processInput(configuration);
        
        Map<String, Object> extensionToFactoryMap = Resource.Factory.Registry.INSTANCE.getExtensionToFactoryMap();
        ResourceSetImpl ecoreRS = performEMFSetup(extensionToFactoryMap);
        
        // load ecore models into registry
        loadEcorePackagesIntoRegistry(configuration, EPackage.Registry.INSTANCE, ecoreRS);
        
        // load inputs into resource set
        ResourceSetImpl resourceSet = loadInputModels(inputs, extensionToFactoryMap);
        
        // initialize obfuscator
        EMFModelObfuscatorBuilder obfuscatorBuilder = EMFModelObfuscatorBuilder.create();
        obfuscatorBuilder.setInput(resourceSet);
        
        if(seed != null) {
            obfuscatorBuilder.setSeed(new BigInteger(seed, 36));
        }
        System.out.println("Obfuscating using seed: " + obfuscatorBuilder.getSeed());
        
        if(salt != null) {
            obfuscatorBuilder.setSalt(salt);
            System.out.println("Obfuscating using salt: " + obfuscatorBuilder.getSalt());
        }
        
        // perform obfuscation
        performObfuscation(obfuscatorBuilder);
        
        // save models to output directory
        saveObfuscatedModels(outputDirectory, inputs, resourceSet);
    }

    /**
     * @param extensionToFactoryMap
     * @return
     */
    private ResourceSetImpl performEMFSetup(Map<String, Object> extensionToFactoryMap) {
        if(!extensionToFactoryMap.containsKey("ecore")) {
            extensionToFactoryMap.put("ecore", new EcoreResourceFactoryImpl());
        }
        ResourceSetImpl ecoreRS = new ResourceSetImpl();
        final ExtendedMetaData extendedMetaData = new BasicExtendedMetaData(EPackage.Registry.INSTANCE);
        ecoreRS.getLoadOptions().put(XMLResource.OPTION_EXTENDED_META_DATA, extendedMetaData);
        return ecoreRS;
    }

    /**
     * @param configuration
     * @return
     */
    private Map<String, URI> processInput(Properties configuration) {
        Map<String,URI> inputs = Maps.newHashMap();
        List<String> resultList = processFileListProperty(configuration, OBFUSCATION_INPUT_PROPERTY);
        for (String filePath : resultList) {
            URI fileURI = URI.createFileURI(filePath);
            inputs.put(filePath,fileURI);
        }
        return inputs;
    }

    /**
     * @param inputs
     * @param extensionToFactoryMap
     * @return
     */
    private ResourceSetImpl loadInputModels(Map<String, URI> inputs, Map<String, Object> extensionToFactoryMap) {
        ResourceSetImpl resourceSet = new ResourceSetImpl();
        for (Entry<String, URI> inputEntry : inputs.entrySet()) {
            URI uri = inputEntry.getValue();
            // XXX we only support XMI resources in this way
            if(!extensionToFactoryMap.containsKey(uri.fileExtension())) {
                extensionToFactoryMap.put(uri.fileExtension(), new EcoreResourceFactoryImpl());
            }
            System.out.println("Loading resource: " + inputEntry.getKey());
            Stopwatch stopwatch = Stopwatch.createStarted();
            resourceSet.getResource(uri, true);
            stopwatch.stop();
            String elapsedTime = stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms (" + stopwatch.elapsed(TimeUnit.NANOSECONDS) + " ns)";
            System.out.println("Loaded resource: " + inputEntry.getKey() + " in " + elapsedTime);
        }
        return resourceSet;
    }

    /**
     * @param configuration
     * @param ePackageRegistryInstance
     * @param ecoreRS
     */
    private void loadEcorePackagesIntoRegistry(Properties configuration,
            org.eclipse.emf.ecore.EPackage.Registry ePackageRegistryInstance, ResourceSetImpl ecoreRS) {
        String ecore = getPropertyValue(configuration, OBFUSCATION_ECORE_PROPERTY);
        StringTokenizer ecoreTokenizer = new StringTokenizer(ecore,";");
        while (ecoreTokenizer.hasMoreTokens()) {
            String ecorePath = (String) ecoreTokenizer.nextToken();
            // create input stream for input files
            Resource ecoreResource = ecoreRS.getResource(URI.createFileURI(ecorePath), true);
            EObject root = ecoreResource.getContents().get(0);
            if(root instanceof EPackage) {
                EPackage ePackage = (EPackage) root;
                ePackageRegistryInstance.put(ePackage.getNsURI(), ePackage);
                System.out.println("Registered metamodel: " + ePackage.getName() + "(nsURI: " + ePackage.getNsURI() + ")");
            }
        }
    }

    /**
     * @param obfuscatorBuilder
     */
    private void performObfuscation(EMFModelObfuscatorBuilder obfuscatorBuilder) {
        AbstractModelObfuscator obfuscator = obfuscatorBuilder.build();
        System.out.println("Obfuscating EMF resource set");
        Stopwatch stopwatch = Stopwatch.createStarted();
        obfuscator.obfuscate();
        stopwatch.stop();
        String elapsedTime = stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms (" + stopwatch.elapsed(TimeUnit.NANOSECONDS) + " ns)";
        System.out.println("Obfuscation finished in: " + elapsedTime);
    }

    /**
     * @param outputDirectory
     * @param inputs
     * @param resourceSet
     */
    private void saveObfuscatedModels(File outputDirectory, Map<String, URI> inputs, ResourceSetImpl resourceSet) {
        URI outputDirUri = URI.createFileURI(outputDirectory.getPath());
        for (Entry<String, URI> entry : inputs.entrySet()) {
            URI uri = entry.getValue();
            String fileSegment = uri.lastSegment();
            URI outputUri = outputDirUri.appendSegment(fileSegment);
            Resource resource = resourceSet.getResource(uri, false);
            resource.setURI(outputUri);
            try {
                System.out.println("Saving resource: " + fileSegment);
                Stopwatch stopwatch2 = Stopwatch.createStarted();
                resource.save(null);
                stopwatch2.stop();
                String elapsedTime2 = stopwatch2.elapsed(TimeUnit.MILLISECONDS) + " ms (" + stopwatch2.elapsed(TimeUnit.NANOSECONDS) + " ns)";
                System.out.println("Saved resource: " + fileSegment + " in " + elapsedTime2);
            } catch (IOException e) {
                reportError("Could not save output " + fileSegment);
            }
        }
    }

    private List<String> processFileListProperty(Properties configuration, String obfuscationInputProperty) {
        List<String> resultList = Lists.newArrayList();
        String input = getPropertyValue(configuration, obfuscationInputProperty);
        StringTokenizer inputTokenizer = new StringTokenizer(input,";");
        while (inputTokenizer.hasMoreTokens()) {
            String inputPath = (String) inputTokenizer.nextToken();
            // create input stream for input files
            File file = new File(inputPath);
            if(!file.exists()) {
                reportError("Input " + file.getPath() + " specified in configuration could not be found");
            }
            if(file.isFile()) {
                String fileName = file.getName();
                if(resultList.contains(fileName)) {
                    reportError("Multiple files with the same name " + fileName + " in configuration");
                }
                resultList.add(inputPath);
            } else if(file.isDirectory()) {
                /*
                 * TODO we could support directories, either processing only directly contained files or all transitive
                 * files. However, we would need to take care in putting the directory structure into the output, handle
                 * symbolic and hard links, etc.
                 */
                reportError("Input" + file.getPath() + " specified in configuration is a directory");
            }
        }
        return resultList;
    }

    /**
     * @param seed
     * @param salt
     * @param configuration
     */
    private void performXMLObfuscation(String seed, String salt, Properties configuration) {
        // ensure output directory existence
        File outputDirectory = checkOutputDirectory(configuration);
        
        // check input file existence
        Map<String,FileInputStream> inputs = Maps.newHashMap();
        prepareInputStreams(configuration, inputs);
        
        // parse schema configuration
        XMLSchemaConfiguration schemaConfiguration = prepareSchemaConfiguration(configuration);
        
        // initialize obfuscator
        XMLModelObfuscatorBuilder obfuscatorBuilder = XMLModelObfuscatorBuilder.create().setSchemaConfiguration(schemaConfiguration);
        
        if(seed != null) {
            obfuscatorBuilder.setSeed(new BigInteger(seed, 36));
        }
        System.out.println("Obfuscating using seed: " + obfuscatorBuilder.getSeed());
        
        if(salt != null) {
            obfuscatorBuilder.setSalt(salt);
            System.out.println("Obfuscating using salt: " + obfuscatorBuilder.getSalt());
        }
        
        performObfuscation(outputDirectory, inputs, obfuscatorBuilder);
    }

    private Properties loadConfigurationPropertyFile(String configPath) throws FileNotFoundException, IOException {
        Properties bundle = new Properties();
        FileInputStream fis = new FileInputStream(configPath);
        try {
            bundle.load(fis);
        } finally {
            fis.close();
        }
        return bundle;
    }

    /**
     * @param configuration
     */
    private File checkOutputDirectory(Properties configuration) {
        String output = getPropertyValue(configuration, OBFUSCATION_OUTPUT_PROPERTY);
        File outputFile = new File(output);
        if(!outputFile.exists()) {
            boolean directoryCreated = outputFile.mkdir();
            if(!directoryCreated) {
                reportError("Output " + output + " specified in configuration could not be created");
            }
        } else if(!outputFile.isDirectory()) {
            reportError("Output " + output + " specified in configuration is not a directory");
        }
        return outputFile;
    }

    private void prepareInputStreams(Properties configuration, Map<String, FileInputStream> inputs) {
        List<String> resultList = processFileListProperty(configuration, OBFUSCATION_INPUT_PROPERTY);
        // create input stream for input files
        for (String fileName : resultList) {
            File file = new File(fileName);
            try {
                FileInputStream fileInputStream = new FileInputStream(file);
                inputs.put(file.getName(),fileInputStream);
            } catch (FileNotFoundException e) {
                reportError("Input " +  file.getPath() + " specified in configuration could not be found, although it exists");
            }
        }
    }

    /**
     * @param configuration
     * @return
     */
    private XMLSchemaConfiguration prepareSchemaConfiguration(Properties configuration) {
        Optional<String> tags = getOptionalPropertyValue(configuration, OBFUSCATION_TAGS_PROPERTY);
        Optional<String> attributes = getOptionalPropertyValue(configuration, OBFUSCATION_ATTRIBUTES_PROPERTY);
        if(!tags.isPresent() && !attributes.isPresent()) {
            reportError("No schema configuration provided, nothing to obfuscate");
        }
        
        Set<String> tagSet = Sets.newHashSet();
        if(tags.isPresent()) {
            StringTokenizer tagTokenizer = new StringTokenizer(tags.get(), ";");
            while (tagTokenizer.hasMoreTokens()) {
                String tag = tagTokenizer.nextToken();
                tagSet.add(tag);
            }
        }
        
        Multimap<String, String> attributeMultimap = HashMultimap.create();
        if(attributes.isPresent()) {
            StringTokenizer attributeTokenizer = new StringTokenizer(attributes.get(), ";");
            while (attributeTokenizer.hasMoreTokens()) {
                String tagAttributes = attributeTokenizer.nextToken();
                try {
                    StringTokenizer tagAttributeTokenizer = new StringTokenizer(tagAttributes, ":");
                    String tagName = tagAttributeTokenizer.nextToken();
                    String attributeList = tagAttributeTokenizer.nextToken();
                    StringTokenizer attributeListTokenizer = new StringTokenizer(attributeList, ",");
                    while (attributeListTokenizer.hasMoreTokens()) {
                        String attributeName = attributeListTokenizer.nextToken();
                        attributeMultimap.put(tagName, attributeName);
                    }
                } catch (NoSuchElementException e) {
                    reportError("Incorrect syntax in attributes value of schema configuration when processing: " + tagAttributes);
                }
            }
        }
        
        XMLSchemaConfiguration schemaConfiguration = new XMLSchemaConfiguration(attributeMultimap, tagSet);
        return schemaConfiguration;
    }

    /**
     * @param outputDirectory
     * @param inputs
     * @param obfuscatorBuilder
     */
    private void performObfuscation(File outputDirectory, Map<String, FileInputStream> inputs,
            XMLModelObfuscatorBuilder obfuscatorBuilder) {
        for (Entry<String, FileInputStream> input : inputs.entrySet()) {
            BufferedInputStream bufferedInputStream = new BufferedInputStream(input.getValue());
            obfuscatorBuilder.setInput(bufferedInputStream);
            String fileName = input.getKey();
            File output = new File(outputDirectory, fileName);
            BufferedOutputStream bufferedOutputStream;
            try {
                bufferedOutputStream = new BufferedOutputStream(new FileOutputStream(output));
                obfuscatorBuilder.setOutput(bufferedOutputStream);
                XMLModelObfuscator obfuscator = obfuscatorBuilder.build();
                System.out.println("Obfuscating " + fileName);
                Stopwatch stopwatch = Stopwatch.createStarted();
                obfuscator.obfuscate();
                stopwatch.stop();
                System.out.println("Obfuscation finished in: " + stopwatch.elapsed(TimeUnit.MILLISECONDS) + " ms (" + stopwatch.elapsed(TimeUnit.NANOSECONDS) + " ns)");
                bufferedOutputStream.close();
                bufferedInputStream.close();
            } catch (FileNotFoundException e) {
                reportError("Could not ouput to file " + output.getPath());
            } catch (IOException e) {
                reportError("Could not close output file " + output.getPath());
            }
        }
    }

    /**
     * @param configuration
     * @return
     */
    private String getPropertyValue(Properties configuration, String propertyName) {
        Optional<String> optionalPropertyValue = getOptionalPropertyValue(configuration, propertyName);
        if(!optionalPropertyValue.isPresent()) {
            reportError(propertyName + " undefined in configuration");
        }
        return optionalPropertyValue.get();
    }
    
    /**
     * @param configuration
     * @return
     */
    private Optional<String> getOptionalPropertyValue(Properties configuration, String propertyName) {
        String propertyValue = configuration.getProperty(propertyName);
        return Optional.fromNullable(propertyValue);
    }

    /**
     * @return
     */
    private Integer reportError(String message) {
        System.out.println(message);
        displayHelp();
        throw new IllegalArgumentException(message);
    }

    private void displayHelp() {
        System.out.println("Usage:\n"
                + "<call> -c <configurationFilePath> [-s <seed>] [-salt <salt>]\n"
                + "  -c       : Required, the configuration that describes what to obfuscate.\n"
                + "  --config : Same as -c.\n"
                + "  -s       : Optional, the seed used for the obfuscation. Must be base 36 number as string\n"
                + "  --seed   : Same as -s.\n"
                + "  --salt   : Optional, the salt used for the obfuscation.");
    }
    
}
