package org.apache.tools.ant.taskdefs.optional.starteam;

import org.apache.tools.ant.*;
import org.apache.tools.ant.taskdefs.*;

import java.util.*;
import java.text.*;
import java.io.*;


/**
 *  an implementation of an ANT task that can get and label files
 *  in a StarTeam repository.  This task understands the following
 *  commands:
 *  <starteam cmd={ [get|co] [label] } folder={stcmd folder path}
 *            dest={local directory} label={text label} recurse=[true|false]
 *            desc={text description} quiet={true|false} noexec={true|false}
 *            date={date of revisions for get or label} />
 *  where cmd is one of:
 *  get|co - retrieves the files according to the <code>folder</code> parameter
 *           specification. Use the <code>label</code> parameter to specify
 *           a specific set of revisions to be retrieved otherwise the tip
 *           revision is retrieved.
 *  label - label the specified files with the text label specified by the
 *          <code>label</code> parameter.
 *  checkin|ci - checks in a file
 *	apply-label|apply - applies labels
 *
 *  and the parameters are:
 *  date  - For GET command, return the files specified as of the requested
 *          date.  For LABEL command, label the files with the requested label
 *          as of the this date.  Note that for GET command, only one of
 *          date or label can be specified for the returned files.
 *  label - The text label to be associated with the tip revisions of each file
 *          specified in the folder parameter specification. <code>label</code>
 *          is required for the label command and is optional for the <code>get</code>
 *          command where it specifies the lable revisions to retrieve.
 *  desc -  A description for an applied label. (optional)
 *  recurse - recursively apply cmd to directory structure (optional)
 *  quiet - perform work quietly (optional, default = verbose)
 *  noexec - prepare command line but don't execute it. (optional, default = exec)
 *  filename - (for checkin only) the file to check in
 *
 * @author chrisn@qstrategies.com
 *
 * 
 * CHANGES:
 *	Execute command line directly (without starbase API)
 *	Checkin command
 *  Apply-label command
 *
 * @author Viktor Szathmary <vszathmary@freshdirect.com> 
 */

public class Starteam extends Task
{

	private String stCmd = "stcmd";
    private String folder;  // required
    private String label;   // optional for get, required for label
	private File   dir;     // required
    private String command;
	private String desc;    // optional description for label
	private String date;	// optional date for labeling and getting files
	private String filename;	// optional param for checkin file name
    private boolean recurse = true;
    private boolean quiet = false;
    private boolean noexec = false;

    public void execute() throws BuildException
	{
		Vector args = new Vector(10);
		args.add(stCmd);
				
		if ( command.equalsIgnoreCase("get") || command.equalsIgnoreCase("co") )
		{
			args.add("co");
			args.add("-x");

	    	if (folder != null)
			{
	    		args.add("-p");
				args.add(folder);
			}
			else
				throw new BuildException( "the Starteam folder parameter must be specified for get");

	    	if (dir != null)
			{
				args.add("-rp");
				args.add(dir.toString());
			}
			else
				throw new BuildException( "the destination folder parameter must be specified for get");

	    	if (label != null)  // label is optional for get
			{
				args.add("-vl");
				args.add(label);
			}

			if ( date != null)
			{
	    		args.add("-vd");
				args.add(date);
			}

			if ( recurse )
			{
				args.add("-is");
			}

		}
		else if ( command.equalsIgnoreCase("label") )
		{
			args.add("label");
			args.add("-x");

	    	if (folder != null)
			{
				args.add("-p");
				args.add(folder);
			}
			else
				throw new BuildException( "the Starteam folder parameter must be specified for labeling");

	    	if ( label != null)
			{
	    		args.add("-nl");
				args.add(label);
			}
			else
				throw new BuildException( "the label parameter must be specified for the label command");

	    	if ( desc != null)
			{
	    		args.add("-d");
				args.add(desc);
			}

			/*
			SimpleDateFormat formatter = new SimpleDateFormat ("MM/dd/yyyy hh:mm a");
			String dateString = null;
			if ( date != null)
			{
				// Parse the previous string back into a Date.
				ParsePosition pos = new ParsePosition(0);
				//  reformat date string to common format
				dateString = formatter.format(formatter.parse(date, pos));
			}
			else
			{
				//  format the current date/time
				dateString = formatter.format(new Date());
			}
			//add the date parameter
    		args.add("-vd");
			args.add(dateString);
			*/

			//  make all labels "revision" labels
			args.add("-r");
		}
		else if ( command.equalsIgnoreCase("apply-label") || command.equalsIgnoreCase("apply") )
		{
			args.add("apply-label");
			args.add("-x");

	    	if (folder != null)
			{
				args.add("-p");
				args.add(folder);
			}
			else
				throw new BuildException( "the Starteam folder parameter must be specified for labeling");

	    	if ( label != null)
			{
	    		args.add("-lbl");
				args.add(label);
			}
			else
				throw new BuildException( "the label parameter must be specified for the label command");

			if ( recurse )
			{
				args.add("-is");
			}

		} else if ( command.equalsIgnoreCase("ci") || command.equalsIgnoreCase("checkin") )
		{
			args.add("ci");
			args.add("-x");
			
			if (folder != null)
			{
	    		args.add("-p");
				args.add(folder);
			}
			else
				throw new BuildException( "the Starteam folder parameter must be specified for get");

	    	if (dir != null)
			{
				args.add("-rp");
				args.add(dir.toString());
			}
			else
				throw new BuildException( "the destination folder parameter must be specified for get");

	    	if (label != null)  // label is optional for get
			{
				args.add("-vl");
				args.add(label);
			}

			if (filename != null ) {
				args.add( filename );
			}
			else
				throw new BuildException( "filename for checkin must be specified");
			


		}
		
		//  parameters which all command require
		if ( quiet )
		{
		    args.add("-q");
			args.add("-nologo");
		}
		// RC4 encryption
		//args.add("-encrypt");
		//args.add("RC4");

		String[] temp = new String[args.size()];
	    run((String[]) args.toArray(temp));
    }

	public void setStCmd(String _s) {
        if (_s != null) {

            if (_s.trim().equals(""))
                _s = null;
        }
		stCmd = _s;
	}

    public void setFolder(String _s)
	{
        if (_s != null) {

            if (_s.trim().equals(""))
                _s = null;
        }
		folder = _s;
    }

	public void setDesc(String _s)
	{
        if (_s != null)
        {

            if (_s.trim().equals(""))
                _s = null;
        }
		desc = _s;
	}

	public void setDate(String _s)
	{
        if (_s != null)
		{

            if (_s.trim().equals(""))
                _s = null;
        }
		desc = _s;
	}

    public void setDest(String _s)
	{
		dir  = project.resolveFile(_s);
    }

    public void setCmd(String _s)
	{
		command = _s;
    }

    public void setQuiet(boolean _q)
	{
        quiet = _q;
    }

    public void setNoexec(boolean _ne)
	{
        noexec = _ne;
    }

	public void setRecurse(boolean _r)
	{
		recurse = _r;
	}

	public void setLabel(String _label)
	{
		if ( _label != null )
		{
			if ( _label.trim().equals("") )
				_label = null;
		}
		label = _label;
	}


	public void setFilename(String _fname) {
		if ( _fname != null )
		{
			if ( _fname.trim().equals("") )
				_fname = null;
		}
		filename = _fname;
	}
	
    protected int run(String[] _args) throws BuildException
	{
        int err = -1; // assume the worst

        try
		{
			if ( !quiet )
			{
				String cmdline = "";
				for( int j = 0; j < _args.length; ++j )
					cmdline += _args[j]+" ";
				System.out.println( "Starteam command line: "+cmdline );
			}

            // exec starteam command
			//err = com.starbase.starteam.commandline.StarTeamCmd.run( _args );
            Execute exe = new Execute(new LogStreamHandler(this, 
                                                           Project.MSG_INFO,
                                                           Project.MSG_WARN));
            exe.setAntRun(project);
            exe.setWorkingDirectory(project.getBaseDir());
            //exe.setCommandline(cmd.getCommandline());
            exe.setCommandline(_args);

            err=exe.execute();

            if (err != 0)
			{
				System.out.println( "Arguments to Starteam:" );
				for ( int i = 0; i < _args.length; ++i )
					System.out.println( _args[i] );
        	    throw new BuildException("Starteam returned: "+err, location);
			}
        }
		catch (Exception e)
		{
			System.out.println( e.getMessage() );
            throw new BuildException("Error starteam: " + command, e, location);
        }

        return err;
    }

}

