/*
* Licensed Materials - Property of IBM* and/or HCL**
* UrbanCode Deploy
* UrbanCode Build
* UrbanCode Release
* AnthillPro
* (c) Copyright IBM Corporation 2014, 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 groovy.json.JsonSlurper

import java.util.Collections

import javax.servlet.http.*

import org.apache.http.HttpStatus
import org.apache.http.client.methods.CloseableHttpResponse
import org.apache.http.client.methods.HttpGet
import org.apache.http.util.EntityUtils

import com.urbancode.air.plugin.artifactory.ArtifactoryHelper
import com.urbancode.commons.httpcomponentsutil.HttpClientBuilder
import com.urbancode.commons.util.FilePatternFileFilter
import com.urbancode.commons.util.IO
import com.urbancode.air.AirPluginTool

final AirPluginTool airPluginTool = new AirPluginTool(this.args[0], this.args[1])
final Properties props = airPluginTool.getStepProperties()

def isEmpty(value) {
    return value == null || value.equals("")
}

final def workDir = new File('.').canonicalFile

final def REPO_PATH_SEPARATOR = "/"

def repoName = props['repositoryName']
def artifacts = props['artifacts'].split('\n')
def username = props['username']
def password = props['password']
boolean recursive = Boolean.valueOf(props['recursive'])
def apiKey = props['apiKey'].trim()
def checkHash = props['checkHash']
def repoUrl = props['artifactoryUrl']
boolean allowInsecure = Boolean.valueOf(props['allowInsecure'])
def identityKey = props['identityKey'].trim()

//remove trailing slashes from url
while (repoUrl.endsWith(REPO_PATH_SEPARATOR)) {
    repoUrl = repoUrl.substring(0, repoUrl.length() - 1)
}

String includesString = props['includes']
String excludesString = props['excludes']
def includes = []
def excludes = []
Collections.addAll(includes, includesString.split("\n"))
Collections.addAll(excludes, excludesString.split("\n"))

String proxyHost = props['proxyHost']?.trim()
String proxyPort = props['proxyPort']?.trim()
String proxyPass = props['proxyPass']?.trim()
String proxyUser = props['proxyUser']?.trim()

boolean matchFilePattern (def workDir, def filename, def includes, def excludes) {
    FilePatternFileFilter acceptor = new FilePatternFileFilter(workDir, includes, excludes)
    return acceptor.accept(new File(workDir, filename))
}

def exitVal = 0
int skippedArtifacts = 0
ArtifactoryHelper aHelper = new ArtifactoryHelper(username, password, apiKey, allowInsecure, proxyHost, proxyPort, proxyPass, proxyUser, identityKey)

def searchArtifacts = { searchUrl ->
    println ("[Action] Searching for artifacts at: ${searchUrl}")
    def response = aHelper.executeHttpRequest(searchUrl, new HttpGet(), null)
    if (!response) {
        println ('[Error] Could not find artifacts')
        exitVal=1
        return []
    }
    int status = response.getStatusLine().getStatusCode()
    if (status == HttpStatus.SC_OK) {
        def artifactUris = []
        def jsonString = EntityUtils.toString(response.getEntity())
        def slurper = new JsonSlurper()
        def children = null
        if (recursive) {
            children = slurper.parseText(jsonString).files
        }
        else {
            children = slurper.parseText(jsonString).children
        }
        for (child in children) {
            def isFolder = child.folder.toString()
            if (isFolder.equals("false")) {
                artifactUris.add(child.uri)
            }
        }
        if (artifactUris.size() > 0) {
            println ("[Ok] Found ${artifactUris.size()} artifacts")
        }
        else {
            println ("[Ok] Did not find any child artifacts to download")
        }
        return artifactUris
    }
    else {
        throw new Exception("[Error] Exception searching: " + searchUrl + "\nErrorCode : " + response.getStatusLine().toString())
    }
}

try {
    artifacts.each { artifact ->
        //remove trailing slashes from artifact
        while (artifact.endsWith(REPO_PATH_SEPARATOR)) {
            artifact = artifact.substring(0, artifact.length() - 1)
        }
        String[] attrs = artifact.split('/')
        String version = attrs[attrs.length - 1]
        String searchUrl = repoUrl + REPO_PATH_SEPARATOR + 'api/storage/' + repoName + REPO_PATH_SEPARATOR + artifact
        def artifactUris = null
        if (recursive) {
            artifactUris = searchArtifacts(searchUrl + "?list&deep=1")
        }
        else {
            artifactUris = searchArtifacts(searchUrl)
        }

        for (artifactUri in artifactUris) {
            //get the final filename of the file
            String[] currFile = artifactUri.split(REPO_PATH_SEPARATOR)
            def filename = currFile[currFile.length - 1]
            def filePath = filename
            if (matchFilePattern(workDir, filename, includes, excludes)) {
                if (recursive) {
                    currFile = artifactUri.split(REPO_PATH_SEPARATOR + version + REPO_PATH_SEPARATOR)
                    filePath = currFile[currFile.length - 1]
                }
                File artifactFile = aHelper.downloadFileFromRepo(searchUrl + artifactUri, checkHash.toString())
                if (artifactFile == null) {
                    throw new Exception("[Error] Failed to download artifact : " + artifact)
                }

                File finalFile = new File(workDir, filePath)
                println "[Action] Moving downloaded artifact to: " + finalFile.getAbsolutePath()
                try {
                    if (recursive) {
                        IO.mkdirs(finalFile.getParentFile())
                    }
                    IO.move(artifactFile, finalFile)
                }
                catch (IOException ex) {
                    println ("[Error] Could not move downloaded artifact: ${ex.getMessage()}\n")
                    exitVal=1
                }
                artifactFile.delete()
            }
            else {
                println("[Info] Skipping file '$filename', doesn't match includes/excludes pattern.")
                skippedArtifacts++
            }
        }
    }
}
catch (Exception e) {
    e.printStackTrace()
    exitVal=1
}
println()
println("[Done] Download Complete.")
if (skippedArtifacts > 0) {
    println("[Info] Process excluded $skippedArtifacts artifact(s).")
}
System.exit(exitVal)
