package org.yi.worthing.scott.ant;

import org.apache.tools.ant.BuildException;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.Project;
import org.apache.tools.ant.DirectoryScanner;
import org.apache.tools.ant.taskdefs.MatchingTask;
import com.oroinc.net.ftp.*;
import org.apache.tools.ant.BuildException;
import java.io.*;
import java.lang.*;
import java.util.*;


/**
 * Copies a directory.
 *
 * @author Scott Carlson<a href="mailto:ScottCarlson@email.com">ScottCarlson@email.com</a>
 */

public class ftp extends Task {
  private String msg;
  private String userid;
  private String password;
  private String server;
  private int port;
  FTPClient ftp = null;
  Vector ftpTasks = new Vector();
  private boolean passiveMode = false;

  public void execute() throws BuildException {
    if (userid == null)
        throw new BuildException("No Userid Specified");
    if (password == null)
        throw new BuildException("No Password Specified");
    if (server== null)
        throw new BuildException("No Server Specified");
    ftp = new FTPClient();
    login();
    if (passiveMode)
        ftp.enterLocalPassiveMode();
    Enumeration e = ftpTasks.elements();
    while (e.hasMoreElements())
    {
        FtpTask f = (FtpTask) e.nextElement();
        f.execute(ftp);
    }
    logout();
  }
    private void logout() 
    {
        try {
            if(ftp.isConnected()) {
                ftp.logout();
                ftp.disconnect();
            }
        } catch(FTPConnectionClosedException e1) {
            throw new BuildException("Server closed connection.");
        } catch(IOException e1) {
            throw new BuildException("IO Error.");
        } finally {
            if(ftp.isConnected()) {
                try { ftp.disconnect(); } catch(IOException f) { }
            }
        }
    }

    private void login() throws BuildException
    {
        //ftp.addProtocolCommandListener(new PrintCommandListener( 
        //                                    new PrintWriter(System.out)));
        try {
            int reply;
            ftp.connect(server);
            reply = ftp.getReplyCode();

            if(!FTPReply.isPositiveCompletion(reply)) {
                ftp.disconnect();
                throw new BuildException("FTP server refused connection");
            }
            if(!ftp.login(userid, password)) {
                ftp.logout();
                throw new BuildException("Couldn't Login");
            }
        } catch(IOException e) {
            throw new BuildException("Error connecting...");
        }
  }

  public FtpPush createSend()
  {
    FtpPush f = new FtpPush();
    Project p = this.getProject();
    f.setProject(p);
    ftpTasks.addElement(f);
    return f;
  }

    public void setPassive(String u) { 
        if (u.toLowerCase().equals("true"))
            passiveMode = true;
        else if (u.toLowerCase().equals("false"))
            passiveMode = false;
        else
            throw new BuildException("Invalid argument for passive. true or false only");
    }
    public void setUserid(String u) { this.userid = u; }
    public void setPassword(String p) { this.password = p; }
    public void setServer(String m) { this.server = m; }

    public interface FtpTask { 
          public void execute(FTPClient session) throws BuildException;
    }
    public class FtpPush extends MatchingTask implements FtpTask{
       private String srcDirectory;
       private String tgtDirectory;
       private boolean binaryTransfer = false;
       private Project project =null;
    
       public void setSrcDirectory(String s) { srcDirectory = s; }
       public void setTgtDirectory(String s) { tgtDirectory = s; }

       public void setProject(Project p) { project = p;}
       public void setType(String s) throws BuildException
       {
           if (s.toLowerCase().equals("binary"))
              binaryTransfer = true;
           else if (s.toLowerCase().equals("ascii")) 
              binaryTransfer = false;
           else throw new BuildException("Valid types {binary}, {ascii}");
       }

       private void sendMultipleFiles() throws BuildException
       {
           DirectoryScanner ds = super.getDirectoryScanner(new File(srcDirectory));
           String[] files = ds.getIncludedFiles();
           if (files.length > 0) {
               project.log("Sending " + files.length + " files to " + tgtDirectory, Project.MSG_VERBOSE);
               for (int i=0; i< files.length; i++)
               {
                   String fromFile = files[i];
                   String toFile = tgtDirectory + "/"+fromFile;
                   try {
                       project.log(fromFile +" ==> " + toFile, Project.MSG_VERBOSE);
                       sendOneFile(fromFile, toFile);
                   } catch (Exception ioe) {
                       String msg = "Failed to copy " + fromFile + " to " + 
                                     toFile + " due to " + ioe.getMessage();
                       throw new BuildException(msg);
                   }
               }
           }
       }

       private void sendOneFile(String fromFile, String toFile)
                    throws BuildException
       {
           try {
               if(binaryTransfer)
                   ftp.setFileType(FTP.BINARY_FILE_TYPE);
               if (ftp.storeFile(toFile, new FileInputStream(new File (srcDirectory,fromFile))) == false)
               {
                   if (ftp.getReplyCode() == FTPReply.CODE_553)
                   {
                       String directory = toFile.substring(0,toFile.lastIndexOf('/'));
                       if(!ftp.makeDirectory(directory))
                           throw new BuildException (ftp.getReplyString());
                       else if (ftp.storeFile(toFile, new FileInputStream(fromFile)) == false)
                           throw new BuildException(ftp.getReplyString());
                   }
                   else 
                       throw new BuildException(ftp.getReplyString());
               }
           } catch (BuildException e) {
               throw e;
           } catch (Exception e)
           {
               throw new BuildException(e.getMessage());
           }
       }

       private void getOneFile(String srcDir, String srcFile, 
                               String tgtDir, String tgtFile)
       {
           try {
               if(binaryTransfer)
                   ftp.setFileType(FTP.BINARY_FILE_TYPE);
               OutputStream output;
               output = new FileOutputStream(new File(srcDir, srcFile));
               ftp.retrieveFile(tgtDir+ "/" +tgtFile, output);
           } catch (Exception e)
           {
               throw new BuildException(e.getMessage());
           }
       }

       public void execute(FTPClient session) throws BuildException
       {
           if (srcDirectory == null)
               throw new BuildException("No Source Directory Specified");
           if (tgtDirectory == null)
               throw new BuildException("No Target Directory Specified");
           //sendOneFile(srcDirectory, srcFileName, tgtDirectory, tgtFileName);
           sendMultipleFiles();
       }
    }

}

