/*
 *
 *  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.Logger;
import flex2.compiler.config.ConfigurationException;
import flex2.compiler.util.CompilerMessage;
import flex2.compiler.util.CompilerMessage.CompilerError;
import flex2.compiler.util.ThreadLocalToolkit;
import flex2.tools.oem.Message;
import org.apache.flex.compiler.clients.COMPC;
import org.apache.flex.compiler.clients.MXMLC;
import org.apache.flex.compiler.clients.MXMLJSC.JSOutputType;
import org.apache.flex.compiler.clients.problems.ProblemQuery;
import org.apache.flex.compiler.clients.problems.ProblemQueryProvider;
import org.apache.flex.compiler.config.Configuration;
import org.apache.flex.compiler.config.ConfigurationBuffer;
import org.apache.flex.compiler.config.ConfigurationValue;
import org.apache.flex.compiler.filespecs.FileSpecification;
import org.apache.flex.compiler.internal.config.FileConfigurator;
import org.apache.flex.compiler.problems.CompilerProblemSeverity;
import org.apache.flex.compiler.problems.ICompilerProblem;
import org.apache.flex.compiler.problems.annotations.DefaultSeverity;
import org.apache.flex.utils.ArgumentUtil;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.lang.reflect.InvocationTargetException;
import java.util.*;

import static org.apache.flex.compiler.clients.MXMLJSC.JSOutputType.FLEXJS_DUAL;

/**
 * Common base class for most flex tools.
 */
public class Tool {
    protected static Class<? extends MXMLC> COMPILER;
    protected static Class<? extends MxmlJSC> JS_COMPILER;

    protected static int compile(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        int exitCode;

        final JSOutputType jsOutputType = JSOutputType.fromString(ArgumentUtil.getValue(args, "-js-output-type"));

        if (jsOutputType != null) {
            ArgumentBag bag = preparePhase1(new ArgumentBag(args));

            MxmlJSC mxmlJSC = JS_COMPILER.newInstance();
            exitCode = mxmlJSC.execute(bag.args);

            if (!mxmlJSC.getProblemQuery().hasErrors()) {
                if (jsOutputType.equals(FLEXJS_DUAL)) {
                    preparePhase2(bag);
                    exitCode = flexCompile(bag.args);
                }
            } else {
                processProblemReport(mxmlJSC);
            }
        } else {
            exitCode = flexCompile(args);
        }

        return exitCode;
    }

    protected static ArgumentBag preparePhase1(ArgumentBag bag) {
        bag.isCommandLineOutput = true;

        bag.oldOutputPath = ArgumentUtil.getValue(bag.args, "-output");

        if (bag.oldOutputPath == null) {
            bag.isCommandLineOutput = false;
            ConfigurationBuffer flexConfig = null;

            try {
                flexConfig = loadConfig(bag.args);
            } catch (org.apache.flex.compiler.exceptions.ConfigurationException ignored) {
            }

            final List<ConfigurationValue> output = flexConfig != null ? flexConfig.getVar("output") : null;
            final ConfigurationValue configurationValue = output != null ? output.get(0) : null;
            bag.oldOutputPath = configurationValue != null ? configurationValue.getArgs().get(0) : null;
        }

        if (bag.oldOutputPath != null) {
            final int lastIndexOf = Math.max(bag.oldOutputPath.lastIndexOf("/"), bag.oldOutputPath.lastIndexOf("\\"));

            if (lastIndexOf > -1) {
                bag.newOutputPath = bag.oldOutputPath.substring(0, lastIndexOf) + File.separator + "js" + File.separator + "out";

                if (bag.isCommandLineOutput) {
                    ArgumentUtil.setValue(bag.args, "-output", bag.newOutputPath);
                } else {
                    bag.args = ArgumentUtil.addValueAt(bag.args, "-output", bag.newOutputPath, bag.args.length - 1);
                }
            }
        }

        return bag;
    }

    protected static ArgumentBag preparePhase2(ArgumentBag bag) {
        bag.args = ArgumentUtil.removeElement(bag.args, "-js-output-type");

        if (bag.oldOutputPath != null) {
            if (bag.isCommandLineOutput) {
                ArgumentUtil.setValue(bag.args, "-output", bag.oldOutputPath);
            } else {
                bag.args = ArgumentUtil.removeElement(bag.args, "-output");
            }
        }

        if (COMPILER.getName().equals(COMPC.class.getName())) {
            bag.args = ArgumentUtil.addValueAt(bag.args, "-include-file", "js" + File.separator + "out" + File.separator + "*," + bag.newOutputPath, bag.args.length - 1);
        }

        return bag;
    }

    private static ConfigurationBuffer loadConfig(String[] args) throws org.apache.flex.compiler.exceptions.ConfigurationException {
        final String configFilePath = ArgumentUtil.getValue(args, "-load-config");
        final File configFile = new File(configFilePath);
        final FileSpecification fileSpecification = new FileSpecification(configFile.getAbsolutePath());
        final ConfigurationBuffer cfgbuf = createConfigurationBuffer(Configuration.class);

        FileConfigurator.load(
                cfgbuf,
                fileSpecification,
                new File(configFile.getPath()).getParent(),
                "flex-config",
                false);

        return cfgbuf;
    }

    private static ConfigurationBuffer createConfigurationBuffer(
            Class<? extends Configuration> configurationClass) {
        return new ConfigurationBuffer(
                configurationClass, Configuration.getAliases());
    }

    protected static int flexCompile(String[] args) throws NoSuchMethodException, InstantiationException, IllegalAccessException, InvocationTargetException {
        int exitCode;

        MXMLC mxmlc = COMPILER.newInstance();
        exitCode = mxmlc.execute(args);
        processProblemReport(new CompilerRequestableProblems(mxmlc));

        return exitCode;
    }

    public static Map<String, String> getLicenseMapFromFile(String fileName) throws ConfigurationException {
        Map<String, String> result = null;
        FileInputStream in = null;

        try {
            in = new FileInputStream(fileName);
            Properties properties = new Properties();
            properties.load(in);
            Enumeration enumeration = properties.propertyNames();

            if (enumeration.hasMoreElements()) {
                result = new HashMap<String, String>();

                while (enumeration.hasMoreElements()) {
                    String propertyName = (String) enumeration.nextElement();
                    result.put(propertyName, properties.getProperty(propertyName));
                }
            }
        } catch (IOException ioException) {
            LocalizationManager l10n = ThreadLocalToolkit.getLocalizationManager();
            throw new ConfigurationException(l10n.getLocalizedTextString(new FailedToLoadLicenseFile(fileName)));
        } finally {
            if (in != null) {
                try {
                    in.close();
                } catch (IOException ioe) {
                }
            }
        }

        return result;
    }

    public static class FailedToLoadLicenseFile extends CompilerError {
        private static final long serialVersionUID = -2980033917773108328L;

        public String fileName;

        public FailedToLoadLicenseFile(String fileName) {
            super();
            this.fileName = fileName;
        }
    }

    public static void processProblemReport(ProblemQueryProvider requestableProblems) {
        for (ICompilerProblem problem : requestableProblems.getProblemQuery().getProblems()) {
            Class aClass = problem.getClass();
            Annotation[] annotations = aClass.getAnnotations();

            for (Annotation annotation : annotations) {
                if (annotation instanceof DefaultSeverity) {
                    DefaultSeverity myAnnotation = (DefaultSeverity) annotation;
                    CompilerProblemSeverity cps = myAnnotation.value();
                    String level;
                    if (cps.equals(CompilerProblemSeverity.ERROR))
                        level = Message.ERROR;
                    else if (cps.equals(CompilerProblemSeverity.WARNING))
                        level = Message.WARNING;
                    else
                        break; // skip if IGNORE?
                    CompilerMessage msg = new CompilerMessage(level,
                            problem.getSourcePath(),
                            problem.getLine() + 1,
                            problem.getColumn());
                    try {
                        String errText = (String) aClass.getField("DESCRIPTION").get(aClass);
                        while (errText.contains("${")) {
                            int start = errText.indexOf("${");
                            int end = errText.indexOf("}", start);
                            String token = errText.substring(start + 2, end);
                            String value = (String) aClass.getField(token).get(problem);
                            token = "${" + token + "}";
                            errText = errText.replace(token, value);
                        }

                        msg.setMessage(errText);
                        logMessage(msg);
                    } catch (IllegalArgumentException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (SecurityException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (IllegalAccessException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    } catch (NoSuchFieldException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
            }

        }
    }

    private static void logMessage(CompilerMessage msg) {

        final Logger logger = ThreadLocalToolkit.getLogger();

        if (logger != null) {
            if (msg.getLevel().equals(Message.INFO)) {
                logger.logInfo(msg.getPath(), msg.getLine(), msg.getColumn(), msg.getMessage());
            } else if (msg.getLevel().equals(Message.WARNING)) {
                logger.logWarning(msg.getPath(), msg.getLine(), msg.getColumn(), msg.getMessage());
            } else if (msg.getLevel().equals(Message.ERROR)) {
                logger.logError(msg.getPath(), msg.getLine(), msg.getColumn(), msg.getMessage());
            }
        }
    }

    public static class NoUpdateMessage extends CompilerMessage.CompilerInfo {
        private static final long serialVersionUID = 6943388392279226490L;
        public String name;

        public NoUpdateMessage(String name) {
            this.name = name;
        }
    }

    static class CompilerRequestableProblems implements ProblemQueryProvider {
        private MXMLC mxmlc;

        public CompilerRequestableProblems(MXMLC mxmlc) {
            this.mxmlc = mxmlc;
        }

        @Override
        public ProblemQuery getProblemQuery() {
            return mxmlc.getProblems();
        }
    }

    protected static class ArgumentBag {
        public String[] args;

        public String oldOutputPath;
        public String newOutputPath;
        public boolean isCommandLineOutput;

        public ArgumentBag(String[] args) {
            this.args = args;
        }
    }
}
