/*
 *
 *  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.flex.swc;

import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.xml.stream.XMLOutputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamWriter;

import org.apache.flex.compiler.Messages;
import org.apache.flex.compiler.clients.problems.ProblemFormatter;
import org.apache.flex.compiler.clients.problems.ProblemPrinter;
import org.apache.flex.compiler.clients.problems.ProblemQuery;
import org.apache.flex.compiler.clients.problems.WorkspaceProblemFormatter;
import org.apache.flex.compiler.common.DependencyType;
import org.apache.flex.compiler.common.DependencyTypeSet;
import org.apache.flex.compiler.common.VersionInfo;
import org.apache.flex.compiler.config.CommandLineConfigurator;
import org.apache.flex.compiler.config.Configuration;
import org.apache.flex.compiler.config.ConfigurationBuffer;
import org.apache.flex.compiler.config.ConfigurationPathResolver;
import org.apache.flex.compiler.config.ConfigurationValue;
import org.apache.flex.compiler.config.Configurator;
import org.apache.flex.compiler.exceptions.ConfigurationException;
import org.apache.flex.compiler.internal.config.annotations.Arguments;
import org.apache.flex.compiler.internal.config.annotations.Config;
import org.apache.flex.compiler.internal.config.annotations.InfiniteArguments;
import org.apache.flex.compiler.internal.config.annotations.Mapping;
import org.apache.flex.compiler.internal.config.annotations.SoftPrerequisites;
import org.apache.flex.compiler.internal.config.localization.LocalizationManager;
import org.apache.flex.compiler.internal.projects.FlexProject;
import org.apache.flex.compiler.internal.projects.LibraryDependencyGraph;
import org.apache.flex.compiler.internal.targets.SWFTarget;
import org.apache.flex.compiler.internal.workspaces.Workspace;
import org.apache.flex.compiler.problems.ConfigurationProblem;
import org.apache.flex.compiler.problems.FileIOProblem;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.InternalCompilerProblem;
import org.apache.flex.compiler.targets.ITargetSettings;
import org.apache.flex.compiler.units.ICompilationUnit;
import org.apache.flex.swc.catalog.XMLFormatter;

/**
 * swcdepends command line utility.
 * 
 * Use this utility to see the dependency order of all SWCs in your configuration.
 * You can also see:
 * 
 * - the swcs a swc is dependent on (on by default).
 * - the scripts that are causing the dependency (off by default).
 * - the dependency types of the scripts (off by default).
 * 
 */
public class SWCDepends
{

    // XML names
    public static final String SWC_DEPENDENCY_ORDER_ELEMENT = "swc-dependency-order";
    public static final String SWC_DEPENDENCIES_ELEMENT = "swc-dependencies";
    public static final String SWC_ELEMENT = "swc";
    public static final String DEFINITION_DEPENDENCIES_ELEMENT = "definition-dependencies";
    public static final String DEFINITION_ELEMENT = "def";
    public static final String PATH_ATTRIBUTE = "path";
    public static final String ID_ATTRIBUTE = "id";
    
    static final String NEWLINE = System.getProperty("line.separator");
    private static final String DEFAULT_VAR = "no-default-arg";
    private static final String L10N_CONFIG_PREFIX = "org.apache.flex.compiler.internal.config.configuration";

    protected Workspace workspace;
    protected FlexProject project;
    protected DependencyConfiguration config;
    protected ProblemQuery problems;
    protected ConfigurationBuffer configBuffer;

    protected Configurator projectConfigurator;

    protected ICompilationUnit mainCU;
    protected SWFTarget target;
    protected ITargetSettings targetSettings;
    
    private List<String> dependencyOrder;     // of all discovered swcs
    
    /**
     * Entry point for <code>swcdepends</code> tool.
     *
     * @param args command line arguments
     */
    public static void main(final String[] args)
    {
        int exitCode = staticMainNoExit(args);
        System.exit(exitCode);
    }


    public static int staticMainNoExit(final String[] args)
    {
        final SWCDepends swcDepends = new SWCDepends();
        return swcDepends.mainNoExit(args);
    }

    public SWCDepends()
    {
        workspace = new Workspace();
        project = new FlexProject(workspace);
        problems = new ProblemQuery();
    }

    public int mainNoExit(final String[] args)
    {
        int result = 0;
        
        if (configure(args))
        {
            XMLStreamWriter xmlWriter = null;
            try
            {
                List<String> showSwcs = config.getShowSwcs();
                DependencyTypeSet dependencyTypes = getDependencyTypeSet();
                LibraryDependencyGraph graph = project.createLibraryDependencyGraph(dependencyTypes);
                
                
                xmlWriter = new XMLFormatter(getXMLWriter());
                xmlWriter.writeStartDocument();
                
                // write SWCDependencyOrder
                xmlWriter.writeStartElement(SWC_DEPENDENCY_ORDER_ELEMENT);

                dependencyOrder = graph.getDependencyOrder();
                for (String swcName : dependencyOrder)
                {
                    if (!showSwc(swcName, showSwcs))
                        continue;
                    
                    println(swcName + ":");

                    xmlWriter.writeStartElement(SWC_ELEMENT);
                    xmlWriter.writeAttribute(PATH_ATTRIBUTE, swcName);

                    // Show the dependencies of this swc.
                    printDependencies(swcName, xmlWriter, graph);
                    
                    xmlWriter.writeEndElement(); // SWC
                }
                
                xmlWriter.writeEndElement(); // SWC_DEPENDENCY_ORDER
                xmlWriter.writeEndDocument();
                xmlWriter.flush();
                xmlWriter.close();
            }
            catch (IOException e)
            {
                final FileIOProblem problem = new FileIOProblem(e);
                problems.add(problem);
            }
            catch (Exception e)
            {
                final ICompilerProblem problem = new InternalCompilerProblem(e);
                problems.add(problem);
            }
            finally
            {
                if (xmlWriter != null)
                {
                    try
                    {
                        xmlWriter.close();
                    }
                    catch (XMLStreamException e)
                    {
                        // ignore
                    }
                }
            }
        }
        else
        {
            result = 1;
        }

        // Print out any errors we may have encountered
        ProblemFormatter formatter = new WorkspaceProblemFormatter(workspace, null);

        ProblemPrinter printer = new ProblemPrinter(formatter, System.err);
        printer.printProblems(problems.getFilteredProblems());

        if( problems.hasErrors() )
            result = 1;

        return result;
    }
    
    /**
     * @param swcName name of swc
     * @param swcs list of swcs to show. An empty list means show all.
     * @return true if the swc should be shown, false otherwise.
     */
    private boolean showSwc(String swcName, List<String>swcs)
    {
        // filter the swcs that are shown
        boolean show = true;
        if (swcs.size() != 0)
        {
            show = false;
            for (String showSwc : swcs)
            {
                if (swcName.endsWith(showSwc))
                {
                    show = true;
                    break;
                }
            }
        }
      
        return show;
    }


    /**
     * Print the dependencies of a SWC.
     * 
     * @param xmlWriter
     * @param graph
     * @throws XMLStreamException 
     */
    private void printDependencies(String swcName, XMLStreamWriter xmlWriter, LibraryDependencyGraph graph) throws XMLStreamException
    {
        // show swc dependencies
        if (config.getShowDependencyList())
        {
            Set<String> dependencies = graph.getDependencies(swcName);
            
            if (dependencies.size() > 0)
            {
                xmlWriter.writeStartElement(SWC_DEPENDENCIES_ELEMENT);
                
                // Sort by dependency order so the swcs are always
                // in the same order.
                List<String> swcDependencies = new ArrayList<String>(graph.getDependencies(swcName));
                Collections.sort(swcDependencies, 
                        new Comparator<String>()
                        {
                            @Override
                            public int compare(String o1, String o2)
                            {
                                return dependencyOrder.indexOf(o1) - dependencyOrder.indexOf(o2);
                            }
                            
                        });
                
                List<String> swcFilter = config.getShowDependentSwcs();
                for (String swcDependency : swcDependencies)
                {
                    if (!showSwc(swcDependency, swcFilter))
                        continue;
                    
                    println("\t" + swcDependency);
                    
                    xmlWriter.writeStartElement(SWC_ELEMENT);
                    xmlWriter.writeAttribute(PATH_ATTRIBUTE, swcDependency);

                    printExterns(swcName, swcDependency, xmlWriter, graph);
                    
                    xmlWriter.writeEndElement(); // SWC
                }
                xmlWriter.writeEndElement(); // SWC_DEPENDENCY_ORDER
            }
        }
        
    }

    /**
     * Print the external scripts that are causing the dependency.
     * 
     * @param swcDependency
     * @param xmlWriter
     * @param graph
     * @throws XMLStreamException 
     */
    private void printExterns(String swcName, String swcDependency, 
            XMLStreamWriter xmlWriter, LibraryDependencyGraph graph) 
            throws XMLStreamException
    {
        // list the external scripts that caused the dependencies between
        // swcLocation and swcDepName.
        if (config.getShowExterns())
        {
            xmlWriter.writeStartElement(DEFINITION_DEPENDENCIES_ELEMENT);
            
            Map<String, DependencyTypeSet> dependencyMap = graph.getDependencySet(swcName, swcDependency); 
            for (Map.Entry<String, DependencyTypeSet> entry : dependencyMap.entrySet()) 
            {
                xmlWriter.writeStartElement(DEFINITION_ELEMENT);
                xmlWriter.writeAttribute(ID_ATTRIBUTE, entry.getKey());

                if (config.getShowTypes())
                {
                    System.out.print("\t\t" + entry.getKey() + "\t");
                    
                    StringBuilder sb = new StringBuilder();
                    for (Iterator<DependencyType>iter = entry.getValue().iterator(); 
                         iter.hasNext();)
                    {
                        DependencyType type = iter.next();
                        
                        System.out.print(type.getSymbol());
                        sb.append(type.getSymbol());
                        
                        if (iter.hasNext())
                        {
                            sb.append(",");
                            System.out.print(" ");
                        }
                    }
                    
                    println("");
                    xmlWriter.writeAttribute("types", sb.toString());
                }
                else
                {
                    println("\t\t" + entry.getKey());
                }
                
                xmlWriter.writeEndElement(); // SCRIPT_NAME
            }
            
            xmlWriter.writeEndElement(); // DEPENDENT_SCRIPTS
        }
    }

    /**
     * @return A writer for the xml-based dependency report.
     * 
     * @throws XMLStreamException 
     * @throws IOException 
     */
    private XMLStreamWriter getXMLWriter() throws XMLStreamException, IOException
    {
        Writer writer = null;
        if (config.getDependencyReport() != null)
            writer = new FileWriter(config.getDependencyReport());
        else
            writer = new StringWriter();    // throw away output

        final XMLOutputFactory xmlOutputFactory = XMLOutputFactory.newInstance();
        assert xmlOutputFactory != null : "Expect XMLOutputFactory implementation.";

        return xmlOutputFactory.createXMLStreamWriter(writer);
    }


    /**
     * @return the dependency set requested by the user. The default to 
     * to show all dependency types.
     */
    private DependencyTypeSet getDependencyTypeSet()
    {
        List<String> desiredDependencies = config.getDesiredScriptDependencyTypes();
        if (desiredDependencies != null)
        {
            DependencyTypeSet dependencySet = DependencyTypeSet.noneOf();
            List<String> validDependencies = new ArrayList<String>();
            for (DependencyType type : DependencyTypeSet.allOf())
            {
                validDependencies.add(String.valueOf(type.getSymbol()));
            }
            
            // convert strings to a enum set.
            for (String desiredDependency : desiredDependencies)
            {
                if (validDependencies.contains(desiredDependency))
                    dependencySet.add(DependencyType.get(desiredDependency.charAt(0)));
            }
            
            return dependencySet;
        }
        
        return DependencyTypeSet.allOf();
    }

    /**
     * Load configurations from all the sources.
     * 
     * @param args command line arguments
     * @return True if mxmlc should continue with compilation.
     */
    protected boolean configure(final String[] args)
    {
        projectConfigurator = createConfigurator();
        
        try
        {
            ConfigurationPathResolver resolver = new ConfigurationPathResolver(System.getProperty("user.dir")); 
            projectConfigurator.setConfigurationPathResolver(resolver);
            projectConfigurator.setConfiguration(args, getConfigurationDefaultVariable());
            projectConfigurator.applyToProject(project);
            problems = new ProblemQuery(projectConfigurator.getCompilerProblemSettings());
            
            // Get the configuration and configBuffer which are now initialized.
            config = (DependencyConfiguration)projectConfigurator.getConfiguration();
            Messages.setLocale(config.getToolsLocale());
            configBuffer = projectConfigurator.getConfigurationBuffer();
            problems.addAll(projectConfigurator.getConfigurationProblems());

            // Print version if "-version" is present.
            if (configBuffer.getVar("version") != null)
            {
                println(VersionInfo.buildMessage());
                return false;
            }

            // Print help if "-help" is present.
            final List<ConfigurationValue> helpVar = configBuffer.getVar("help");
            if (helpVar != null)
            {
                processHelp(helpVar);
                return false;
            }
            
            for (String fileName : projectConfigurator.getLoadedConfigurationFiles())
            {
                println(Messages.getString("MXMLC.Loading_configuration_format", 
                        Collections.<String,Object>singletonMap("configurationName", fileName)));                
            }
            
            // Add a blank line between the configuration list and the rest of 
            // the output to make the start of the output easier to detect.
            println(""); 
            
            // If we have configuration errors then exit before trying to 
            // validate the target.
            if (problems.hasErrors())
                return false;
            
            return true;
        }
        catch (Exception e)
        {
            final ICompilerProblem problem = new ConfigurationProblem(null, -1, -1, -1, -1, e.getMessage());
            problems.add(problem);
            return false;
        }
    }
    
    /**
     * Print detailed help information if -help is provided.
     */
    private void processHelp(final List<ConfigurationValue> helpVar)
    {
        final Set<String> keywords = new LinkedHashSet<String>();
        for (final ConfigurationValue val : helpVar)
        {
            for (final Object element : val.getArgs())
            {
                String keyword = (String)element;
                while (keyword.startsWith("-"))
                    keyword = keyword.substring(1);
                keywords.add(keyword);
            }
        }

        if (keywords.size() == 0)
            keywords.add("help");

        final String usages = CommandLineConfigurator.usage(
                    getProgramName(),
                    DEFAULT_VAR,
                    configBuffer,
                    keywords,
                    LocalizationManager.get(),
                    L10N_CONFIG_PREFIX);
        println(getStartMessage());
        println(usages);
    }
    
    /**
     * Print a message.
     * 
     * @param msg Message text.
     */
    protected void println(final String msg)
    {
        System.out.println(msg);
    }

    /**
     * Get the start up message that contains the program name with the
     * copyright notice.
     * 
     * @return the start up message.
     */
    private String getStartMessage()
    {
        // This must not be localized.
        String message = "SWC Dependency utility (swcdepends)" + NEWLINE +
            VersionInfo.buildMessage() + NEWLINE;
        return message;
    }

    private String getConfigurationDefaultVariable()
    {
        return DEFAULT_VAR;
    }

    private Configurator createConfigurator()
    {
        return new Configurator(DependencyConfiguration.class);
    }


    /**
     * @return always "swcdepends"
     */
    private String getProgramName()
    {
        return "swcdepends";
    }

    /**
     * dependency.* configuration options
     *
     */
    public static class DependencyConfiguration extends Configuration
    {

        //
        // 'show-external-classes' option
        //
        //  Should we show the external scripts
        //
        
        private boolean showExterns = false;

        public boolean getShowExterns()
        {
            return showExterns;
        }

        @Config
        @Mapping({"dependency", "show-external-classes"})
        public void setShowExternalClasses(ConfigurationValue cv, boolean showExterns) throws ConfigurationException
        {
            this.showExterns = showExterns;
        }

        //
        // 'show-dependency-list' option
        //
        //  Should swc dependencies be shown in addition to the dependency 
        //  order?
        //
        
        private boolean showDependencyList = true;

        public boolean getShowDependencyList()
        {
            return showDependencyList;
        }

        @Config
        @Mapping({"dependency", "show-dependency-list"})
        public void setShowDependencyList(ConfigurationValue cv, boolean showSwcDependencies) throws ConfigurationException
        {
            this.showDependencyList = showSwcDependencies;
        }

        //
        // 'show-types' option
        //
        //  Should we show the external scripts
        //
        
        private boolean showTypes = false;

        public boolean getShowTypes()
        {
            return showTypes;
        }

        @Config
        @Mapping({"dependency", "show-types"})
        @SoftPrerequisites("show-external-classes")
        public void setShowTypes(ConfigurationValue cv, boolean showTypes) throws ConfigurationException
        {
            this.showTypes = showTypes;
            
            // if showTypes is set, then turn on show-external-classes show the types will be seen.
            if (showTypes)
                showExterns = true;
        }

        //
        // 'types' option
        //
        
        private List<String> desiredTypes = new LinkedList<String>();
        
        public List<String> getDesiredScriptDependencyTypes()
        {
            return desiredTypes;
        }
        
        @Config(allowMultiple=true)
        @Mapping({"dependency", "types"})
        @Arguments("type")
        @InfiniteArguments
        public void setTypes( ConfigurationValue cfgval, String[] types ) throws ConfigurationException
        {
            for (int i = 0; i < types.length; ++i)
            {
                desiredTypes.add( types[i] );
            }
        }

        //
        // 'show-swcs' option
        //
        //  Filter which SWCs to show in the dependency order.
        //
        
        private List<String> showSwcs = new LinkedList<String>();
        
        public List<String> getShowSwcs()
        {
            return showSwcs;
        }
        
        @Config(allowMultiple = true)
        @Mapping({"dependency", "show-swcs"})
        @Arguments("swc-name")
        @InfiniteArguments
        public void setShowSwcs(ConfigurationValue cfgval, String[] swcs) throws ConfigurationException
        {
            for (int i = 0; i < swcs.length; ++i)
            {
                showSwcs.add(swcs[i]);
            }
        }

        //
        // 'show-swcs' option
        //
        //  Filter which SWCs to show in the "dependent SWCs" list. 
        //
        
        private List<String> showDependentSwcs = new LinkedList<String>();
        
        public List<String> getShowDependentSwcs()
        {
            return showDependentSwcs;
        }
        
        @Config(allowMultiple = true)
        @Mapping({"dependency", "show-dependent-swcs"})
        @Arguments("swc-name")
        @InfiniteArguments
        public void setShowDependentSwcs(ConfigurationValue cfgval, String[] swcs) throws ConfigurationException
        {
            for (int i = 0; i < swcs.length; ++i)
            {
                showDependentSwcs.add(swcs[i]);
            }
        }

        //
        // 'minimize-dependency-set' option
        //
        //  Removes a SWC from the dependency set if the scripts resolved in a SWC are a subset of the scripts resolved in another dependent SWC.
        //  No longer supported, the dependency set is always minimized.
        //
        
        @Config(removed=true)
        @Mapping({"dependency", "minimize-dependency-set"})
        public void setMinimizeDependencySet(ConfigurationValue cv, boolean minimumSet) throws ConfigurationException
        {
            // leave configuration option here so old scripts do not error.
        }
        
        // 
        // -dependency-report option
        //
        // Takes a path that specifies a filename where an xml version of the report
        // is written.
        
        private String dependencyReportFileName;
        
        public File getDependencyReport()
        {
            return dependencyReportFileName != null ? new File(dependencyReportFileName) : null;
        }

        @Config()
        @Mapping({"dependency", "dependency-report"})
        @Arguments("filename")
        public void setDependencyReport(ConfigurationValue cv, String filename)
        {
            this.dependencyReportFileName = getOutputPath(cv, filename);
        }
        
    }

}
