/*
 *
 *  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.royale.formatter.config;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.TreeMap;

import org.apache.royale.compiler.common.IPathResolver;
import org.apache.royale.compiler.exceptions.ConfigurationException;
import org.apache.royale.compiler.filespecs.FileSpecification;
import org.apache.royale.compiler.internal.config.localization.LocalizationManager;
import org.apache.royale.compiler.internal.config.localization.ResourceBundleLocalizer;
import org.apache.royale.compiler.problems.ConfigurationProblem;
import org.apache.royale.compiler.problems.ICompilerProblem;
import org.apache.royale.formatter.internal.config.FileConfigurator;
import org.apache.royale.formatter.internal.config.SystemPropertyConfigurator;
import org.apache.royale.utils.FilenameNormalization;
import org.apache.royale.utils.Trace;

/**
 * A class that allows a client change compiler settings and to 
 * configure projects and targets from those settings.
 */
public class Configurator implements Cloneable
{
    /**
     * Convert file path strings to {@code File} objects. Null values are
     * discarded.
     * 
     * @param paths List of file paths
     * @return List of File objects. No null values will be returned.
     */
    public static List<File> toFiles(final List<String> paths)
    {
        final List<File> result = new ArrayList<File>();
        for (final String path : paths)
        {
            if (path != null)
                result.add(new File(path));
        }
        return result;
    }

    /**
     * Convert file path strings to {@code File} objects. Null values are
     * discarded.
     * 
     * @param paths List of file paths
     * @return Array of File objects. No null values will be returned.
     */
    public static List<File> toFileList(final List<String> paths)
    {
        final List<File> result = new ArrayList<File>();
        for (final String path : paths)
        {
            if (path != null)
                result.add(FilenameNormalization.normalize(new File(path)));
        }
        return result;
    }

    /**
     * Convert {@code File} objects to {@code String}, where each {@code String} is 
     * the absolute file path of the file. Null values are discarded.
     * 
     * @param files file specifications
     * @return Array of File objects. No null values will be returned.
     */
    public static String[] toPaths(File[] files)
    {
        final List<String> result = new ArrayList<String>();
        for (final File file : files)
        {
            if (file != null)
                result.add(file.getAbsolutePath());
        }
        return result.toArray(new String[0]);
    }

    // Used to generate the command line
    private static final String EQUALS_STRING = "=";
    private static final String PLUS_EQUALS_STRING = "+=";
    private static final String COMMA_STRING =  ",";
    private static final String PLUS_STRING =  "+";
    /**
     * Constructor
     */
    public Configurator()
    {
        this(Configuration.class);
    }
    
    /**
     * Constructor
     */
    public Configurator(Class<? extends Configuration> configurationClass)
    {
        this.configurationClass = configurationClass;
        args = new LinkedHashMap<String, Object>();
        more = new LinkedHashMap<String, Object>();
        tokens = new TreeMap<String, String>();
        
        isConfigurationDirty = true;
        configurationDefaultVariable = IFormatterSettingsConstants.FILES; // the default variable of the configuration.
        configurationProblems = new ArrayList<ICompilerProblem>();

        // initialize the localization manager.
        LocalizationManager.get().addLocalizer(new ResourceBundleLocalizer());
    }

    private ConfigurationBuffer cfgbuf;
    protected Configuration configuration;
    private Class<? extends Configuration> configurationClass;
    
    private Map<String, Object> args, more;
    private String[] extras;
    private String configurationDefaultVariable;
    private List<String> loadedConfigFiles;
    private List<String> missingConfigFiles;
    
    private Map<String, String> tokens;
    
    private boolean isConfigurationDirty;
    private boolean configurationSuccess;
    protected Collection<ICompilerProblem> configurationProblems;
    private IPathResolver configurationPathResolver;

    // 
    // IConfigurator related methods
    //

    public List<String> getLoadedConfigurationFiles()
    {
        return loadedConfigFiles != null ? loadedConfigFiles :
            Collections.<String>emptyList();
    }

    public List<String> getMissingConfigurationFiles()
    {
        return missingConfigFiles != null ? missingConfigFiles :
            Collections.<String>emptyList();
    }

    public Collection<ICompilerProblem> validateConfiguration(String[] args)
    {
        if (args == null)
            throw new NullPointerException("args may not be null");
        
        List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>();
        ConfigurationBuffer configurationBuffer = createConfigurationBuffer(configurationClass);
        
        try
        {
            CommandLineConfigurator.parse(configurationBuffer, null, args);
        }
        catch (ConfigurationException e)
        {
            final ICompilerProblem problem = new ConfigurationProblem(e);
            problems.add(problem);
        }
        
        return problems;
    }
    
    public Collection<ICompilerProblem> getConfigurationProblems()
    {
        assert configuration != null : 
            "Get the configuration problems after calling getConfiguration()";
        
        List<ICompilerProblem> problems = new ArrayList<ICompilerProblem>(configurationProblems.size() +
                                            configuration.getConfigurationProblems().size());
        problems.addAll(configurationProblems);
        problems.addAll(configuration.getConfigurationProblems()); 
        return problems;
    }

    public void setConfigurationPathResolver(IPathResolver pathResolver)
    {
        if (pathResolver == null)
            throw new NullPointerException("pathResolver may not be null");

        this.configurationPathResolver = pathResolver;
    }

    public Configuration getConfiguration()
    {
        processConfiguration();
        return configuration;
    }
    
    public ConfigurationBuffer getConfigurationBuffer()
    {
        return cfgbuf;
    }

    /**
     * Create a new configuration instance. The Configurator will need to 
     * create a new configuration for each new configuration. For example,
     * creating a new Configurator and getting the target settings will create
     * a new configuration. If later on, the configuration is modified by calling
     * any of the setter methods on the Configurator, then a new configuration 
     * will be created the next time applyToProject() or getTargetSettings() is called.
     * 
     * The method may be overriden to allow for greater control when creating a 
     * custom configuration that extends the built-in configuration.
     * 
     * @return a new configuration instance. If the custom configuration class
     * cannot be created, the default configuration class will be created instead.
     */
    protected Configuration createConfiguration()
    {
        try
        {
            return configurationClass.newInstance();
        }
        catch (Exception e)
        {
            // If there is a problem initializing the configuration, then
            // throw a ConfigurationException.
            reportConfigurationException(new ConfigurationException.CouldNotInstantiate(configurationClass.getName()));

            // Create the default configuration so we can report configuration
            // problems.
            try
            {
                return Configuration.class.newInstance();                
            }
            catch (Exception e2)
            {
                // this should never fail
                assert(false);
                return null;
            }
        }
    }
    
    /**
     * Initialize the configuration and the configuration buffer.
     */
    protected void initializeConfiguration()
    {
        // Create a clean configuration and configuration buffer
        configuration = createConfiguration();
        cfgbuf = createConfigurationBuffer(configuration.getClass());
        assert configurationPathResolver != null : "No configuration path resolver was set.";
        configuration.setPathResolver(configurationPathResolver);
    }

    /**
     * Create a configuration buffer.
     * @param configurationClass    The Configuration object
     * @return          the configuration buffer to use
     */
    protected ConfigurationBuffer createConfigurationBuffer(
            Class<? extends Configuration> configurationClass)
    {
        return new ConfigurationBuffer(
                configurationClass, Configuration.getAliases());
    }

    /**
     * Wrapper around the real processConfiguration.
     * 
     * @return true if success, false otherwise.
     */
    protected boolean processConfiguration()
    {
        boolean success = true;
        
        if (isConfigurationDirty)
        {
            configurationProblems.clear();
            
            try
            {
                success = processConfiguration(getOptions(args, more, processExtras(extras)));
            }
            catch (ConfigurationException e)
            {
                reportConfigurationException(e);
                success = false;
            }
            catch (Exception e)
            {
            	e.printStackTrace();
            }
        }
        else
        {
            success = configurationSuccess;
        }
        
        isConfigurationDirty = false;
        configurationSuccess = success;
        return success;
    }

    /**
     * Does all the work to set the command line arguments info the 
     * configuration object.
     *  
     * @param argsArray - command line arguments
     * 
     * @return true if successful, false otherwise.
     */
    protected boolean  processConfiguration(String[] argsArray)
    {
        initializeConfiguration();
        
        boolean success = true;

        try
        {   
            SystemPropertyConfigurator.load(cfgbuf, "royale");

            // Parse the command line a first time, to peak at stuff like
            // "royalelib" and "load-config".  The first parse is thrown
            // away after that and we intentionally parse a second time
            // below.  See note below.
            CommandLineConfigurator.parse(cfgbuf, configurationDefaultVariable, argsArray);

            overrideDefaults();

            // Return if "-version" is present so the command line can print the 
            // version.
            if (cfgbuf.getVar("version") != null)
                return false;

            // Return so the command line can print help if "-help" is present.
            final List<ConfigurationValue> helpVar = cfgbuf.getVar("help");
            if (helpVar != null)
                return false;

            // Load configurations from files.
            if (!loadConfig())
                success = false;

            if (!loadLocalConfig())
                success = false;
            
            // The command line needs to take precedence over all defaults and config files.
            // By simply re-merging the command line back on top,
            // we will get the behavior we want.
            cfgbuf.clearSourceVars(CommandLineConfigurator.source);
            CommandLineConfigurator.parse(cfgbuf, configurationDefaultVariable, argsArray);

            // commit() reports problems instead of throwing an exception. This 
            // allows us to process all the options in a configuration that
            // are correct in the hopes that it will be enough to configure a
            // project.
            if (!cfgbuf.commit(configuration, configurationProblems))
                success = false;
            
            configuration.validate(cfgbuf);
        }
        catch (ConfigurationException e)
        {
            reportConfigurationException(e);
            success = false;
        }
        
        return success;
    }

    /**
     * Override default values.
     */
    protected void overrideDefaults() throws ConfigurationException
    {
    }

    /**
     * Load configuration XML file specified in {@code -load-config} option on
     * command-line.
     * 
     * @return true if successful, false otherwise.
     */
    protected boolean loadConfig()
    {
        boolean success = true;
        
        List<ConfigurationValue> configs;
        try
        {
            configs = cfgbuf.peekConfigurationVar("load-config");
            if (configs != null)
            {
                for (ConfigurationValue cv : configs)
                {
                    for (String path : cv.getArgs())
                    {
                        File configFile = configurationPathResolver.resolve(path);
                        if (!configFile.exists())
                        {
                            success = false;
                            if (missingConfigFiles == null)
                                missingConfigFiles = new ArrayList<String>();
                            
                            missingConfigFiles.add(path);
                        }
                        else 
                        {
                           if (!loadConfigFromFile(
                                    cfgbuf,
                                    configFile,
                                    new File(configFile.getPath()).getParent(),
                                    "asformat-config",
                                    false))
                           {
                               success = false;
                           }
                        }
                    }
                }
            }
        }
        catch (ConfigurationException e)
        {
            reportConfigurationException(e);
            success = false;
        }

        return success;
    }

    /**
     * Load project specific configuration. The configuration XML file is at the
     * project root with naming convention of asformat-config.xml.
     * 
     * @return true if successful, false otherwise.
     */
    protected boolean loadLocalConfig()
    {
        boolean success = true;
        
        String project = "asformat-config.xml";
        File projectFile = configurationPathResolver.resolve(project);
        if (projectFile.exists())
        {
            if (!loadConfigFromFile(
                    cfgbuf,
                    projectFile,
                    new File(project).getParent(),
                    "asformat-config",
                    false))
            {
                success = false;
            }
        }
        
        return success;
    }

    /**
     * Load a configuration from file. {@code FileConfigurator.load()} is
     * wrapped in this method because we want to print a message after loading
     * using MXMLC#println(String).
     * 
     * @return true if successful, false otherwise.
     */
    protected final boolean loadConfigFromFile(final ConfigurationBuffer buffer,
                                          final File fileSpec,
                                          final String context,
                                          final String rootElement,
                                          final boolean ignoreUnknownItems)
    {
        boolean success = true;
        
        try
        {
            FileConfigurator.load(buffer, 
                    new FileSpecification(fileSpec.getAbsolutePath()),
                    context, rootElement, ignoreUnknownItems);
        }
        catch (ConfigurationException e)
        {
            // record exception
            reportConfigurationException(e);
            success = false;
            
        }

        if (loadedConfigFiles == null)
            loadedConfigFiles = new ArrayList<String>();
        
        loadedConfigFiles.add(fileSpec.getPath());
        
        return success;
    }

    /**
     * Convert conifguration exceptions to problems and collect them for 
     * reporting.
     * 
     * @param e
     */
    protected void reportConfigurationException(ConfigurationException e)
    {
        final ICompilerProblem problem = new ConfigurationProblem(e);
        configurationProblems.add(problem);
    }
    
    //
    // Configuration related methods
    //
    protected String[] getOptions(Map<String, Object> args, Map<String, Object> more, 
		String[] extras)
    {
        ArrayList<String> buffer = new ArrayList<String>();
        
        for (Map.Entry<String, String> tokenEntry : tokens.entrySet())
        {
            buffer.add(PLUS_STRING + tokenEntry.getKey() + EQUALS_STRING + tokenEntry.getValue());
        }
        
        for (Map.Entry<String, Object> arg : args.entrySet())
        {
            String key = arg.getKey();
            Object value = arg.getValue();

            if (value instanceof Boolean)
            {
                buffer.add(key + EQUALS_STRING + value);
            }
            else if (value instanceof Number)
            {
                buffer.add(key);
                buffer.add(value.toString());
            }
            else if (value instanceof String)
            {               
                if (!"".equals(value))
                {
                    buffer.add(key);
                    buffer.add((String)value);
                }
                else
                {
                    buffer.add(key + EQUALS_STRING);
                }
            }
            else if (value instanceof File)
            {
                String p = ((File) value).getPath();
                if (!"".equals(p))
                {
                    buffer.add(key);
                    buffer.add(p);
                }
                else
                {
                    buffer.add(key + EQUALS_STRING);
                }
            }
            else if (value instanceof java.util.Date)
            {
                buffer.add(key);
                buffer.add(value.toString());
            }
            else if (value instanceof Map)
            {
                @SuppressWarnings("unchecked")
                Map<String, ?> m = (Map<String, ?>) value;
                for (Map.Entry<String, ?>entry : m.entrySet())
                {
                    String k = entry.getKey();
                    Object v = entry.getValue();
                    
                    if (v instanceof String)
                    {
                        buffer.add(key);
                        buffer.add(k);
                        buffer.add((String)v);
                    }
                    else if (v instanceof File)
                    {
                        buffer.add(key);
                        buffer.add(k);
                        buffer.add(((File) v).getPath());
                    }
                    else if (v instanceof Collection)
                    {
                        buffer.add(key);
                        buffer.add(k);
                        Collection<?> list = (Collection<?>)v;
                        for (Object next : list)
                        {
                            if (next != null)
                                buffer.add(next.toString());
                        }
                    }
                    else if (v != null)
                    {
                        assert false;
                    }
                }
            }
            else if (value instanceof int[])
            {
                int[] a = (int[]) value;
                buffer.add(key);
                buffer.add(String.valueOf(a[0]));
                buffer.add(String.valueOf(a[1]));
            }
            else if (value instanceof Collection)
            {
                Collection<Object> list = new LinkedList<Object>((Collection<?>)args.get(key));
                
                int length = list.size();
                if (length > 0)
                {
                    buffer.add(key);
                }
                for (Object obj : list)
                {
                    if (obj instanceof String)
                    {
                        buffer.add((String)obj);
                    }
                    else if (obj instanceof File)
                    {
                        buffer.add(((File)obj).getPath());
                    }
                }
            }
            else if (value != null)
            {
                assert false;
            }
            else
            {
                // System.err.println("unprocessed compiler options: " + key + EQUALS_STRING + value);
            }
        }
        
        for (Map.Entry<String, Object> moreEntry : more.entrySet())
        {
            String key = moreEntry.getKey();
            Object value = moreEntry.getValue();

            if (value instanceof Collection)
            {
                buffer.add(key + PLUS_EQUALS_STRING + toCommaSeparatedString((Collection<?>)value));
            }
            else if (value instanceof Map)
            {
                @SuppressWarnings("unchecked")
                Map<String, ?> m = (Map<String, ?>) value;
                for (Map.Entry<String, ?>entry : m.entrySet())
                {
                    String k = entry.getKey();
                    Object v = entry.getValue();
                    
                    if (v instanceof Collection)
                    {
                        buffer.add(key + PLUS_EQUALS_STRING + k + COMMA_STRING +
                                toCommaSeparatedString((Collection<?>)v));
                    }
                    else if (v != null)
                    {
                        assert false;
                    }
                }
            }
            else if (value != null)
            {
                assert false;
            }
            else
            {
                // System.err.println("unprocessed compiler options: " + key + EQUALS_STRING + value);
            }
        }

        // Append extra command line args to the buffer.
        if (extras != null && extras.length > 0)
        {
            for (int i = 0, length = extras == null ? 0 : extras.length; i < length; i++)
            {
                if (extras[i] != null)
                {
                    buffer.add(extras[i]);
                }
            }            
        }
        
        String[] options = new String[buffer.size()];
        buffer.toArray(options);
    
        if (Trace.config)
            Trace.trace("Configurator: options = " + buffer.toString());
        
        return options;
    }

	protected String[] processExtras(String[] extraOptions) throws ConfigurationException
    {
		return extraOptions;
	}

    /**
     * Sets the configuration parameters. The input should be valid <code>mxmlc/compc</code> command-line arguments.<p>
     * 
     * @param args <code>mxmlc/compc</code> command-line arguments
     * @param defaultVariable the default variable of the configuration.
     */
    public void setConfiguration(String[] args, String defaultVariable)
    {
        extras = args;
        configurationDefaultVariable = defaultVariable;
        isConfigurationDirty = true;
    }
    
    /**
     * Defines a token. mxmlc and compc support token substitutions. For example,
     * 
     * <pre>
     * mxmlc +royalelib=path1 +foo=bar --var=${foo}
     * </pre>
     * 
     * <code>var=bar</code> after the substitution of <code>${foo}</code>.
     * 
     * @param name The name of the token.
     * @param value The value of the token.
     */
    public void setToken(String name, String value)
    {
        tokens.put(name, value);
        
        isConfigurationDirty = true;
    }

    /**
     * 
     */
    @Override
    public String toString()
    {
        String[] options;
        try
        {
            options = getOptions(args, more, processExtras(extras));
        }
        catch (ConfigurationException e)
        {
            options = new String[0];
        }
        
        StringBuilder b = new StringBuilder();
        for (int i = 0; i < options.length; i++)
        {
            b.append(options[i]);
            b.append(' ');
        }
        return b.toString();
    }
    
    private String toCommaSeparatedString(Collection<?> values)
    {
        StringBuilder b = new StringBuilder();
        int length = values.size();
        int i = 0;
        for (Object value : values)
        {
            String valueString = null;
            
            if (value instanceof String)
            {
                valueString = (String)value;
            }
            else if (value instanceof File)
            {
                valueString = ((File)value).getPath();
            }
            
            if (valueString != null)
                b.append(valueString);
            
            if (i++ < length - 1)
            {
                b.append(COMMA_STRING);
            }
        }
        return b.toString();
    }
    
    @Override
    public Configurator clone()
    {
        Configurator cloneConfig;
        
        try
        {
            cloneConfig = (Configurator) super.clone();
        }
        catch ( CloneNotSupportedException e )
        {
            throw new RuntimeException(e);//wont happen
        }

        cloneConfig.args = new LinkedHashMap<String, Object>(args);
        cloneConfig.more = new LinkedHashMap<String, Object>(more);
        cloneConfig.tokens = new LinkedHashMap<String, String>(tokens);
        cloneConfig.configurationClass = configurationClass;
        cloneConfig.isConfigurationDirty = true;
        
        if (extras != null)
        {
            cloneConfig.extras = new String[extras.length];
            System.arraycopy(extras, 0, cloneConfig.extras, 0, extras.length);
        }

        return cloneConfig;
    }
}
