/*
* Licensed Materials - Property of IBM* and/or HCL**
* UrbanCode Deploy
* (c) Copyright IBM Corporation 2013, 2017. All Rights Reserved.
* (c) Copyright HCL Technologies Ltd. 2018. All Rights Reserved.
*
* U.S. Government Users Restricted Rights - Use, duplication or disclosure restricted by
* GSA ADP Schedule Contract with IBM Corp.
*
* * Trademark of International Business Machines
* ** Trademark of HCL Technologies Limited
*/

import org.apache.commons.lang3.StringUtils
import org.apache.commons.net.ftp.FTP
import org.apache.commons.net.ftp.FTPClient
import org.apache.commons.net.ftp.FTPFile
import org.apache.commons.net.ftp.FTPReply

import com.urbancode.air.AirPluginTool

// Get step properties
def apTool = new AirPluginTool(this.args[0], this.args[1])
inProps = apTool.getStepProperties()

String host           = inProps['host'].trim()
String port           = inProps['port'].trim()
String username       = inProps['username']
String password       = inProps['password']
String fileNames      = inProps['fileNames'].trim()
String deleteDir      = inProps['deleteDirPath'].trim()
Boolean deleteDirBool = inProps['deleteDirBool'].toBoolean()
String connectionMode = inProps['connectionMode']?.trim()

// Input sanitation
URI hostUri = null
try {
    hostUri = new URI('ftp://' + host)
}
catch (URISyntaxException use) {
    println ('[error]  Invalid URI syntax.')
    println ('[possible solution]  Please update the step configuration with a valid URI for Host.')
    System.exit(1)
}

if (!StringUtils.isNumeric(port)) {
    println ('[error]  The value of the Port property is not numeric.')
    println ('[possible solution]  Please update the step configuration with a numeric value for Port.')
    System.exit(1)
}

if (!deleteDir.startsWith('/')) {
    deleteDir = '/' + deleteDir
}

if (!deleteDir.endsWith('/')) {
    deleteDir = deleteDir + '/'
}

List<String> deleteFiles = fileNames.split(",|\n")*.trim() - [""]

FTPClient ftp = new FTPClient()

// Connect
println ('[action]  Connecting to FTP Server with host: ' + hostUri.getHost() + ', port: ' + port + '...')
try {
    ftp.connect(hostUri.getHost(), port.toInteger())
}
catch (UnknownHostException uhe) {
    println ('[error]  Host "' + host + '" cannot be resolved.')
    println ('[possible solution]  Please update the step configuration with a valid host.')
    System.exit(1)
}
catch (ConnectException ce) {
    println ('[error]  Could not connect to FTP Server.')
    println ('[possible solution]  Ensure the step configuration Hostname property is entered correctly and the FTP server ' +
             'is actively listening for connections.')
    System.exit(1)
}
if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
    println ('[error]  FTP Server refused connection: ' + ftp.getReplyString())
    closeFTPConnection(ftp)
    System.exit(1)
}
println ('[ok]  Connected to FTP Server.')

try {
    // Login
    println ('[action]  Logging into FTP Server...')
    boolean loggedIn = ftp.login(username, password)
    if (!loggedIn) {
        println ('[error]  Could not log in to FTP Server: ' + ftp.getReplyString())
        closeFTPConnection(ftp)
        System.exit(1)
    }
    println ('[ok]  Logged into FTP Server.')

    if (connectionMode == "localPassive") {
        ftp.enterLocalPassiveMode()
        println ('[ok]  Set Local Passive data connection mode.')
    }
    else if (connectionMode == "localActive") {
        ftp.enterLocalActiveMode()
        println ('[ok]  Set Local Active data connection mode.')
    }

    boolean fileDeleteFail = false
    for (file in deleteFiles) {
        println ('\n[action]  Starting to delete file ' + file + ' in ' + deleteDir)
        boolean complete = ftp.deleteFile(deleteDir + file)
        if (complete) {
            println ('[ok]  File ' + deleteDir + file + ' deleted successfully')
        }
        else {
            println ('[error]  File ' + deleteDir + file + ' failed to delete: ' + ftp.getReplyString())
            fileDeleteFail = true
        }
    }

    if (deleteDirBool) {
        println ('\n[action]  Starting to delete folder ' + deleteDir)
        boolean complete = ftp.removeDirectory(deleteDir)
        if (complete) {
            println ('[ok]  Directory ' + deleteDir + ' deleted successfully')
            closeFTPConnection(ftp)
            System.exit(0)
        }
        else {
            println ('[error]  Directory ' + deleteDir + ' failed to delete: ' + ftp.getReplyString())
            closeFTPConnection(ftp)
            System.exit(1)
        }
    }

    if (fileDeleteFail) {
        closeFTPConnection(ftp)
        System.exit(1)
    } else {
        closeFTPConnection(ftp)
        System.exit(0)
    }

} catch (IOException ioe) {
    println ('[error]  Exception caught. Attempting to gracefully close FTP Server connection before printing stacktrace and exiting...')
    ioe.printStackTrace()
} catch (Exception e) {
    println ('[error]  Exception caught. Attempting to gracefully close FTP Server connection before printing stacktrace and exiting...')
    e.printStackTrace()
}
finally {
    if (ftp.isConnected()) {
        closeFTPConnection(ftp)
        System.exit(1)
    }
    else {
        println ('[ok]  FTP Server connection already closed')
        System.exit(1)
    }
}

/**
*  @param ftp The FTPClient to close the connection to
*/
private void closeFTPConnection(FTPClient ftp) {
    try {
        ftp.logout()
        ftp.disconnect()
        println ('[ok]  FTP Server connection closed')
    }
    catch (IOException ioe) {
        println ('[error]  Could not properly logout and disconnect from FTP Server')
        ioe.printStackTrace()
        System.exit(1)
    }
}
