/*
 *
 *  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 flex2.tools;

import flash.localization.LocalizationManager;
import flex2.compiler.common.Configuration;
import flex2.compiler.common.ConfigurationPathResolver;
import flex2.compiler.common.PathResolver;
import flex2.compiler.config.*;
import flex2.compiler.io.VirtualFile;
import flex2.compiler.util.CompilerMessage;
import flex2.compiler.util.ThreadLocalToolkit;
import org.apache.flex.compiler.clients.MXMLC;

import java.io.BufferedInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.InvocationTargetException;
import java.util.*;
import java.util.Map.Entry;

/**
 * A command line tool for compiling Flex applications.  Despite the
 * name, in addition to .mxml files, this tool can be used to compile
 * other file formats, like .as and .css.
 */
public final class Mxmlc extends Tool {
    static private String l10nConfigPrefix = "flex2.configuration";

    public static final String FILE_SPECS = "file-specs";

    /**
     * The entry-point for Mxmlc.
     * Note that if you change anything in this method, make sure to check Compc, Shell, and
     * the server's CompileFilter to see if the same change needs to be made there.  You
     * should also inform the Zorn team of the change.
     *
     * @param args
     */
    public static void main(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        System.exit(mxmlcNoExit(args));
    }

    public static int mxmlcNoExit(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {

        COMPILER = MXMLC.class;
        JS_COMPILER = MxmlJSC.class;

        return compile(args);
    }

    public static void mxmlc(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {

        COMPILER = MXMLC.class;
        JS_COMPILER = MxmlJSC.class;

        compile(args);
    }

    public static Configuration processConfiguration(LocalizationManager lmgr, String program, String[] args,
                                                     ConfigurationBuffer cfgbuf, Class<? extends Configuration> cls, String defaultVar)
            throws ConfigurationException, IOException {
        return processConfiguration(lmgr, program, args, cfgbuf, cls, defaultVar, true);
    }

    public static Configuration processConfiguration(LocalizationManager lmgr, String program, String[] args,
                                                     ConfigurationBuffer cfgbuf, Class<? extends Configuration> cls, String defaultVar,
                                                     boolean ignoreUnknownItems)
            throws IOException {
        ToolsConfiguration toolsConfiguration = null;
        try {
            SystemPropertyConfigurator.load(cfgbuf, "flex");

            // Parse the command line a first time, to peak at stuff like
            // "flexlib" 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, defaultVar, args);

            String flexlib = cfgbuf.getToken("flexlib");
            if (flexlib == null) {
                String appHome = System.getProperty("application.home");

                if (appHome == null) {
                    appHome = ".";
                } else {
                    appHome += File.separator + "frameworks";       // FIXME - need to eliminate this from the compiler
                }
                cfgbuf.setToken("flexlib", appHome);
            }

            // Framework Type
            // halo, gumbo, interop...
            String framework = cfgbuf.getToken("framework");
            if (framework == null) {
                cfgbuf.setToken("framework", "halo");
            }

            String configname = cfgbuf.getToken("configname");
            if (configname == null) {
                cfgbuf.setToken("configname", "flex");
            }

            String buildNumber = cfgbuf.getToken("build.number");
            if (buildNumber == null) {
                if ("".equals(VersionInfo.getBuild())) {
                    buildNumber = "workspace";
                } else {
                    buildNumber = VersionInfo.getBuild();
                }
                cfgbuf.setToken("build.number", buildNumber);
            }


            // We need to intercept "help" options because we want to try to correctly
            // interpret them even when the rest of the configuration is totally screwed up.

            if (cfgbuf.getVar("version") != null) {
                System.out.println(VersionInfo.buildMessage());
                System.exit(0);
            }

            processHelp(cfgbuf, program, defaultVar, lmgr, args);

            // at this point, we should have enough to know both
            // flexlib and the config file.

            ConfigurationPathResolver configResolver = new ConfigurationPathResolver();

            List<ConfigurationValue> configs = cfgbuf.peekConfigurationVar("load-config");

            if (configs != null) {
                for (ConfigurationValue cv : configs) {
                    for (String path : cv.getArgs()) {
                        VirtualFile configFile = ConfigurationPathResolver.getVirtualFile(path, configResolver, cv);
                        cfgbuf.calculateChecksum(configFile);
                        InputStream in = configFile.getInputStream();
                        if (in != null) {
                            FileConfigurator.load(cfgbuf, new BufferedInputStream(in), configFile.getName(),
                                    configFile.getParent(), "flex-config", ignoreUnknownItems);
                        } else {
                            throw new ConfigurationException.ConfigurationIOError(path, cv.getVar(), cv.getSource(), cv.getLine());
                        }
                    }
                }
            }

            PathResolver resolver = ThreadLocalToolkit.getPathResolver();
            // Load project file, if any...
            List fileValues = cfgbuf.getVar(FILE_SPECS);
            if ((fileValues != null) && (fileValues.size() > 0)) {
                ConfigurationValue cv = (ConfigurationValue) fileValues.get(fileValues.size() - 1);
                if (cv.getArgs().size() > 0) {
                    String val = cv.getArgs().get(cv.getArgs().size() - 1);
                    int index = val.lastIndexOf('.');
                    if (index != -1) {
                        String project = val.substring(0, index) + "-config.xml";
                        VirtualFile projectFile = resolver.resolve(configResolver, project);
                        if (projectFile != null) {
                            cfgbuf.calculateChecksum(projectFile);
                            InputStream in = projectFile.getInputStream();
                            if (in != null) {
                                FileConfigurator.load(cfgbuf, new BufferedInputStream(in),
                                        projectFile.getName(), projectFile.getParent(), "flex-config",
                                        ignoreUnknownItems);
                            }
                        }
                    }
                }
            }

            // The command line needs to take precedence over all defaults and config files.
            // This is a bit gross, but by simply re-merging the command line back on top,
            // we will get the behavior we want.
            cfgbuf.clearSourceVars(CommandLineConfigurator.source);
            CommandLineConfigurator.parse(cfgbuf, defaultVar, args);

            toolsConfiguration = null;
            try {
                toolsConfiguration = (ToolsConfiguration) cls.newInstance();
                toolsConfiguration.setConfigPathResolver(configResolver);
            } catch (Exception e) {
                LocalizationManager l10n = ThreadLocalToolkit.getLocalizationManager();
                throw new ConfigurationException(l10n.getLocalizedTextString(new CouldNotInstantiate(toolsConfiguration)));
            }
            cfgbuf.commit(toolsConfiguration);

            // enterprise service config file has other config file dependencies. add them here...
            calculateServicesChecksum(toolsConfiguration, cfgbuf);

            toolsConfiguration.validate(cfgbuf);

            // consolidate license keys...
            VirtualFile licenseFile = toolsConfiguration.getLicenseFile();
            if (licenseFile != null) {
                Map<String, String> fileLicenses = Tool.getLicenseMapFromFile(licenseFile.getName());
                Map<String, String> cmdLicenses = toolsConfiguration.getLicensesConfiguration().getLicenseMap();
                if (cmdLicenses == null) {
                    toolsConfiguration.getLicensesConfiguration().setLicenseMap(fileLicenses);
                } else if (fileLicenses != null) {
                    fileLicenses.putAll(cmdLicenses);
                    toolsConfiguration.getLicensesConfiguration().setLicenseMap(fileLicenses);
                }
            }
        } catch (ConfigurationException e) {
            e.printStackTrace();
        }

        return toolsConfiguration;
    }

    static void processHelp(ConfigurationBuffer cfgbuf, String program, String defaultVar, LocalizationManager lmgr, String[] args) {
        if (cfgbuf.getVar("help") != null) {
            Set<String> keywords = new HashSet<String>();
            List vals = cfgbuf.getVar("help");
            for (Iterator it = vals.iterator(); it.hasNext(); ) {
                ConfigurationValue val = (ConfigurationValue) it.next();
                for (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");
            }

            ThreadLocalToolkit.logInfo(getStartMessage(program));
            System.out.println();
            System.out.println(CommandLineConfigurator.usage(program, defaultVar, cfgbuf, keywords, lmgr, l10nConfigPrefix));
            System.exit(0);
        }

        if (args.length == 0 && ("mxmlc".equals(program) || "compc".equals(program))) {
            ThreadLocalToolkit.logInfo(getStartMessage(program));
            System.err.println(CommandLineConfigurator.brief(program, defaultVar, lmgr, l10nConfigPrefix));
            System.exit(1);
        }
    }

    private static void calculateServicesChecksum(Configuration config, ConfigurationBuffer cfgbuf) {
        Map<String, Long> services = null;
        if (config.getCompilerConfiguration().getServicesDependencies() != null) {
            services = config.getCompilerConfiguration().getServicesDependencies().getConfigPaths();
        }

        if (services != null) {
            for (Entry<String, Long> entry : services.entrySet()) {
                cfgbuf.calculateChecksum(entry.getKey(), entry.getValue());
            }
        }
    }

    public static void processConfigurationException(ConfigurationException ex, String program) {
        ThreadLocalToolkit.log(ex);

        if (ex.source == null || ex.source.equals("command line")) {
            Map<String, String> p = new HashMap<String, String>();
            p.put("program", program);
            String help = ThreadLocalToolkit.getLocalizationManager().getLocalizedTextString("flex2.compiler.CommandLineHelp", p);
            if (help != null) {
                // "Use '" + program + " -help' for information about using the command line.");
                System.err.println(help);
            }
        }
    }

    private static String getStartMessage(String program) {
        LocalizationManager l10n = ThreadLocalToolkit.getLocalizationManager();

        return l10n.getLocalizedTextString(new StartMessage(program, VersionInfo.buildMessage()));
    }

    public static class CouldNotInstantiate extends CompilerMessage.CompilerInfo {
        private static final long serialVersionUID = -8970190710117830662L;

        public CouldNotInstantiate(Configuration config) {
            super();
            this.config = config;
        }

        public final Configuration config;
    }

    public static class StartMessage extends CompilerMessage.CompilerInfo {
        private static final long serialVersionUID = 4807822711658875257L;

        public StartMessage(String program, String buildMessage) {
            super();
            this.program = program;
            this.buildMessage = buildMessage;
        }

        public final String program, buildMessage;
    }

    public static class OutputMessage extends CompilerMessage.CompilerInfo {
        private static final long serialVersionUID = -4859993585489031839L;

        public String name;
        public String length;

        public OutputMessage(String name, String length) {
            this.name = name;
            this.length = length;
        }
    }
}

