package fr.jayasoft.ivy.ant;

import java.io.File;
import java.io.InputStream;
import java.io.PrintStream;
import java.util.Vector;

import junit.framework.TestCase;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.BuildLogger;
import org.apache.tools.ant.DefaultLogger;
import org.apache.tools.ant.DemuxInputStream;
import org.apache.tools.ant.DemuxOutputStream;
import org.apache.tools.ant.Main;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.ProjectHelper;
import org.apache.tools.ant.input.DefaultInputHandler;
import org.apache.tools.ant.input.InputHandler;

import fr.jayasoft.ivy.util.FileUtil;

public class AntCallTriggerTest extends TestCase {
	public void test() throws Exception {
		assertFalse(new File("test/triggers/ant-call/A/out/foo.txt").exists());		
		runAnt(new File("test/triggers/ant-call/A/build.xml"), "resolve");
		// should have unzipped foo.zip
		assertTrue(new File("test/triggers/ant-call/A/out/foo.txt").exists());		
	}
	
	protected void tearDown() throws Exception {
		FileUtil.forceDelete(new File("test/triggers/ant-call/A/out"));
		FileUtil.forceDelete(new File("test/triggers/ant-call/cache"));
	}
	
	private void runAnt(File buildFile, String target) throws BuildException {
		runAnt(buildFile, target, Project.MSG_INFO);
	}
	private void runAnt(File buildFile, String target, int messageLevel) throws BuildException {
		Vector targets = new Vector();
		targets.add(target);
		runAnt(buildFile, targets, messageLevel);
	}
	private void runAnt(File buildFile, Vector targets, int messageLevel) throws BuildException {
		runBuild(buildFile, targets, messageLevel);
		
// this exits the jvm at the end of the call
//		Main.main(new String[] {"-f", buildFile.getAbsolutePath(), target});
		
// this does not set the good message level
//		Ant ant = new Ant();
//		Project project = new Project();
//		project.setBaseDir(buildFile.getParentFile());
//		project.init();
//		
//		ant.setProject(project);
//		ant.setTaskName("ant");
//		
//		ant.setAntfile(buildFile.getAbsolutePath());
//		ant.setInheritAll(false);
//		if (target != null) {
//			ant.setTarget(target);
//		}
//		ant.execute();
	}

	//////////////////////////////////////////////////////////////////////////////
	// miserable copy (updated to simple test cases) from ant Main class: 
	// the only available way I found to easily run ant exits jvm at the end
    private void runBuild(File buildFile, Vector targets, int messageLevel) throws BuildException {

        final Project project = new Project();
        project.setCoreLoader(null);

        Throwable error = null;

        try {
            addBuildListeners(project, messageLevel);
            addInputHandler(project, null);

            PrintStream err = System.err;
            PrintStream out = System.out;
            InputStream in = System.in;

            // use a system manager that prevents from System.exit()
            SecurityManager oldsm = null;
            oldsm = System.getSecurityManager();

                //SecurityManager can not be installed here for backwards
                //compatibility reasons (PD). Needs to be loaded prior to
                //ant class if we are going to implement it.
                //System.setSecurityManager(new NoExitSecurityManager());
            try {
            	project.setDefaultInputStream(System.in);
                System.setIn(new DemuxInputStream(project));
                System.setOut(new PrintStream(new DemuxOutputStream(project, false)));
                System.setErr(new PrintStream(new DemuxOutputStream(project, true)));


                project.fireBuildStarted();

                project.init();
                project.setUserProperty("ant.version", Main.getAntVersion());


                project.setUserProperty("ant.file",
                                        buildFile.getAbsolutePath());


                ProjectHelper.configureProject(project, buildFile);

                // make sure that we have a target to execute
                if (targets.size() == 0) {
                    if (project.getDefaultTarget() != null) {
                        targets.addElement(project.getDefaultTarget());
                    }
                }

                project.executeTargets(targets);
            } finally {
                // put back the original security manager
                //The following will never eval to true. (PD)
                if (oldsm != null) {
                    System.setSecurityManager(oldsm);
                }

                System.setOut(out);
                System.setErr(err);
                System.setIn(in);
            }
        } catch (RuntimeException exc) {
            error = exc;
            throw exc;
        } catch (Error err) {
            error = err;
            throw err;
        } finally {
        	project.fireBuildFinished(error);
        }
    }


    /**
     * Adds the listeners specified in the command line arguments,
     * along with the default listener, to the specified project.
     *
     * @param project The project to add listeners to.
     *                Must not be <code>null</code>.
     */
    protected void addBuildListeners(Project project, int level) {

        // Add the default listener
        project.addBuildListener(createLogger(level));

    }

    /**
     * Creates the InputHandler and adds it to the project.
     *
     * @param project the project instance.
     * @param inputHandlerClassname 
     *
     * @exception BuildException if a specified InputHandler
     *                           implementation could not be loaded.
     */
    private void addInputHandler(Project project, String inputHandlerClassname) throws BuildException {
        InputHandler handler = null;
        if (inputHandlerClassname == null) {
            handler = new DefaultInputHandler();
        } else {
            try {
                handler = (InputHandler)
                    (Class.forName(inputHandlerClassname).newInstance());
                if (project != null) {
                    project.setProjectReference(handler);
                }
            } catch (ClassCastException e) {
                String msg = "The specified input handler class "
                    + inputHandlerClassname
                    + " does not implement the InputHandler interface";
                throw new BuildException(msg);
            } catch (Exception e) {
                String msg = "Unable to instantiate specified input handler "
                    + "class " + inputHandlerClassname + " : "
                    + e.getClass().getName();
                throw new BuildException(msg);
            }
        }
        project.setInputHandler(handler);
    }

    // XXX: (Jon Skeet) Any reason for writing a message and then using a bare
    // RuntimeException rather than just using a BuildException here? Is it
    // in case the message could end up being written to no loggers (as the
    // loggers could have failed to be created due to this failure)?
    /**
     * Creates the default build logger for sending build events to the ant
     * log.
     *
     * @return the logger instance for this build.
     */
    private BuildLogger createLogger(int level) {
        BuildLogger logger = null;
            logger = new DefaultLogger();

        logger.setMessageOutputLevel(level);
        logger.setOutputPrintStream(System.out);
        logger.setErrorPrintStream(System.err);

        return logger;
    }

}
