/*
 *
 *  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.compiler.ant;

import java.io.File;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;
import java.util.List;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.types.Commandline;
import org.apache.tools.ant.types.Environment.Variable;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.taskdefs.Java;

import org.apache.flex.compiler.ant.config.ConfigVariable;
import org.apache.flex.compiler.ant.config.NestedAttributeElement;
import org.apache.flex.compiler.ant.config.IOptionSource;
import org.apache.flex.compiler.ant.config.OptionSpec;

/**
 * This class contains common data and logic used by all the Flex Ant tasks.
 */
public abstract class FlexTask extends Java
{
    protected static OptionSpec RUNTIME_SHARED_LIBRARY_PATH =
    	new OptionSpec("runtime-shared-library-path", "rslp");

    /**
     * Constructor.
     * 
     * @param taskName The name of the Ant task.
     * @param configVariables An array of ConfigVariables that will be set by attributes of the task.
     * @param toolJARFileName The build tool's jar file.
     * @param toolClassName The build tool's class name.
     * @param toolMethodName The build tool's method name.
     * @param toolFailureMethodName The build tool's method to determine
     * whether an exit code means failure.
     */
    protected FlexTask(String taskName, ConfigVariable[] configVariables,
    		           String toolJARFileName, String toolClassName,
    		           String toolMethodName, String toolFailureMethodName)
    {
    	this.taskName = taskName;
        this.configVariables = configVariables;
        this.toolJARFileName = toolJARFileName;
        this.toolClassName = toolClassName;
        this.toolMethodName = toolMethodName;
        this.toolFailureMethodName = toolFailureMethodName;

        cmdline = new Commandline();
    }

	/**
	 * The name of the Ant task.
	 */
	private final String taskName;
	
    /**
     * An array of ConfigVariabes that are set by setDynamicAttribute().
     */
    protected final ConfigVariable[] configVariables;

    /**
     * The build tool's jar file name.
     */
    private final String toolJARFileName;

    /**
     * The build tool's class name.
     */
    private final String toolClassName;

    /**
     * The build tool's entry point.
     * It must be a static method that takes a String[]
     * and returns an int exit code.
     */
    private final String toolMethodName;
    
    /**
     * The build tools' method that determines whether the
     * exit code should make the Ant task fail.
     * It must be a static method that takes an int
     * and returns a boolean.
     */
    private final String toolFailureMethodName;

    /**
     * The commandline used in execute()
     */
    protected final Commandline cmdline;

    protected List<IOptionSource> nestedAttribs;

    /**
     * fork attribute
     */
    protected boolean fork;
    
    private ClassLoader originalContextClassLoader;

    protected NestedAttributeElement createElem(String attrib, OptionSpec spec)
    {
        NestedAttributeElement e = new NestedAttributeElement(attrib, spec, this);
        nestedAttribs.add(e);
        return e;
    }

    protected NestedAttributeElement createElem(String[] attribs, OptionSpec spec)
    {
        NestedAttributeElement e = new NestedAttributeElement(attribs, spec, this);
        nestedAttribs.add(e);
        return e;
    }
    
    protected NestedAttributeElement createElemAllowAppend(String[] attribs, OptionSpec spec)
    {
        NestedAttributeElement e = new NestedAttributeElement(attribs, spec, this, true);
        nestedAttribs.add(e);
        return e;
    }

    /*=======================================================================*
     * 	Static Attributes                                                    *
     *=======================================================================*/
    /**
     * Sets whether to run the task in a separate VM.
     *
     * @param f if true then run in a separate VM.
     */
    public void setFork(boolean f)
    {
        super.setFork(f);
        this.fork = f;
    }

    /*=======================================================================*
     *  Dynamic Attributes                                                   *
     *=======================================================================*/

    /**
     * Set the named attribute to the given value.
     *
     * @param attributeName The name of the attribute to set
     * @param value The value to set the named attribute to
     */
    public void setDynamicAttribute(String attributeName, String value)
    {
        ConfigVariable var = null;

        for (int i = 0; i < configVariables.length && var == null; i++)
        {
            if (configVariables[i].matches(attributeName))
                var = configVariables[i];
        }

        if (var != null)
        {
            var.set(value);
        }
        else
        {
            throw new BuildException("The <" + taskName + "> type doesn't support the \"" +
                                     attributeName + "\" attribute.", getLocation());
        }
    }

    /*=======================================================================*
     *  Dynamic Elements                                                     *
     *=======================================================================*/

    public Object createDynamicElement(String elementName)
    {
        ConfigVariable var = null;

        for (int i = 0; i < configVariables.length && var == null; i++)
        {
            if (configVariables[i].matches(elementName))
                var = configVariables[i];
        }

        if (var != null)
        {
            return createElem(elementName, var.getSpec());
        }
        else
        {
            throw new BuildException("The <" + taskName + "> type doesn't support the \"" +
                                     elementName + "\" nested element.", getLocation());
        }
    }

    /*=======================================================================*
     *  Execute and Related Functions                                        *
     *=======================================================================*/

    /**
     * Called by execute after the set ConfigVariables in <code>vars</code> has
     * been added to the commandline. This function is responsible for adding
     * all tool-specific options to the commandline as well as setting the
     * default options of a build tool.
     */
    protected abstract void prepareCommandline() throws BuildException;

    /**
     * Execute the task
     *
     * @throws BuildException If running build tool failed
     */
    public final void execute() throws BuildException
    {
        String flexHomeProperty = getProject().getProperty("FLEX_HOME");

        if (flexHomeProperty == null)
            throw new BuildException("FLEX_HOME must be set to use the Flex Ant Tasks");
		
        String falconHomeProperty = getProject().getProperty("FALCON_HOME");
        if (falconHomeProperty == null)
            throw new BuildException("FALCON_HOME must be set to use the Flex Ant Tasks");
				
        System.setProperty("FLEX_HOME", flexHomeProperty);
        String flexlibProperty = flexHomeProperty.concat("/frameworks/");
		System.setProperty("flexlib", flexlibProperty);

        final Variable variable = new Variable();
        variable.setKey("flexlib");
        variable.setValue(flexHomeProperty);
		addSysproperty(variable);
        
        // This allows the tool to find the default config file.
        cmdline.createArgument().setValue("+flexlib=" + flexlibProperty);
        
        prepareCommandline();

        if (fork)
            executeOutOfProcess();
        else
            executeInProcess();
    }

    /**
     * Executes the task in a separate VM
     */
    private void executeOutOfProcess() throws BuildException
    {
        try
        {
        	// Without this, the tool class won't be found by executeJava().
        	Class<?> toolClass = resolveClass(toolClassName);
        	
            super.setClassname(toolClassName);

            // convert arguments into a string for use by executeJava()
            // also auto-quotes arguments with spaces
            String line = Commandline.toString(cmdline.getArguments());
            super.createArg().setLine(line);

            int exitCode = super.executeJava();

            // Check exit code.
            if (isFatalFailure(toolClass, exitCode))
                throw new BuildException(taskName + " task failed.");
        }
        finally
        {
            if (originalContextClassLoader != null)
                Thread.currentThread().setContextClassLoader(originalContextClassLoader);
        }
    }

    /**
     * Executes the task in the same VM
     */
    private void executeInProcess() throws BuildException
    {
        try
        {
            Class<?> toolClass = resolveClass(toolClassName);

            log("FlexTask.execute: " + cmdline, Project.MSG_DEBUG);
            
            int exitCode = -1;

            try
            {
                Method toolMethod = toolClass.getMethod(toolMethodName, new Class[] {String[].class});
                Object result = toolMethod.invoke(null, new Object[] {cmdline.getArguments()});
                exitCode = ((Integer)result).intValue();
            }
            catch (Exception e)
            {
                StringWriter stringWriter = new StringWriter();
                PrintWriter printWriter = new PrintWriter(stringWriter);
                e.printStackTrace(printWriter);
                log(stringWriter.toString(), Project.MSG_DEBUG);
                throw new BuildException("Unable to run " + toolMethodName + ": " + e.getMessage(), e);
            }

            if (isFatalFailure(toolClass, exitCode))
                throw new BuildException(taskName + " task failed");//            }
        }
        finally
        {
            if (originalContextClassLoader != null)
                Thread.currentThread().setContextClassLoader(originalContextClassLoader);
        }
    }

    private boolean isFatalFailure(Class<?> toolClass, int exitCode)
    {
    	boolean fatal = true;
    	
    	try
    	{
			Method toolFailureMethod = toolClass.getMethod(toolFailureMethodName, new Class[] {int.class});
			Object result = toolFailureMethod.invoke(null, new Object[] {exitCode});
			fatal = ((Boolean)result).booleanValue();
		}
    	catch (Exception e)
    	{
            StringWriter stringWriter = new StringWriter();
            PrintWriter printWriter = new PrintWriter(stringWriter);
            e.printStackTrace(printWriter);
            log(stringWriter.toString(), Project.MSG_DEBUG);
            throw new BuildException("Unable to run " + toolFailureMethodName + ": " + e.getMessage(), e);
		}
    	
    	return fatal;
    }

    private Class<?> resolveClass(String className)
    {
        Class<?> result = null;

        try
        {
            result = Class.forName(className, true, Thread.currentThread().getContextClassLoader());
        }
        catch (ClassNotFoundException ignoredClassNotFoundException)
        {
            String flexHomeProperty = getProject().getProperty("FALCON_HOME");

            if (flexHomeProperty != null)
            {
                File flexHome = new File(flexHomeProperty);

                if ( flexHome.exists() )
                {
                    File jarFile = new File(flexHome + "/lib", toolJARFileName);

                    if (jarFile.exists())
                    {
                        try
                        {
                        	URL url = jarFile.toURI().toURL();
                            URLClassLoader urlClassLoader = new URLClassLoader(new URL[] {url});
                            result = Class.forName(className, true, urlClassLoader);
                            originalContextClassLoader = Thread.currentThread().getContextClassLoader();
                            Thread.currentThread().setContextClassLoader(urlClassLoader);
                            
							if (fork)
								super.setClasspath(new Path(getProject(), jarFile.getAbsolutePath()));
                        }
                        catch (MalformedURLException malformedURLException)
                        {
                            // We shouldn't really get here, but just in case.
                            malformedURLException.printStackTrace();
                        }
                        catch (ClassNotFoundException classNotFoundException)
                        {
                            throw new BuildException("The class " + className + " was not found in jar file " + toolJARFileName,
                                                     getLocation());
                        }
                    }
                    else
                    {
                        throw new BuildException("File does not exist: " + toolJARFileName, getLocation());
                    }
                }
                else
                {
                    throw new BuildException("FALCON_HOME does not exist.", getLocation());
                }
            }
            else
            {
                throw new BuildException("The class, " + className +
                                         ", must be in the classpath or the FALCON_HOME property must be set.",
                                         getLocation());
            }
        }

        return result;
    }
}
