/**
 * Licensed Materials - Property of IBM* and/or HCL**
 * UrbanCode Deploy
 * (c) Copyright IBM Corporation 2011, 2018. All Rights Reserved.
 * (c) Copyright HCL Technologies Ltd. 2018, 2019, 2020. 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 com.urbancode.air.AirPluginTool
import com.urbancode.air.plugin.docker.AmazonECRClient
import com.urbancode.air.plugin.docker.ArtifactoryClient
import com.urbancode.air.plugin.docker.IBMContainerRegistryClient
import com.urbancode.air.plugin.docker.RegistryClient
import com.urbancode.air.plugin.docker.DockerTrustedRegistryClient
import com.urbancode.ud.client.ComponentClient
import com.urbancode.ud.client.VersionClient

import java.util.regex.Matcher
import java.util.regex.Pattern
import java.net.URL

final String VERSION_DOCKER_IMAGE_TAG = "dockerImageTag"; // Docker tag, like "latest"
final String VERSION_DOCKER_IMAGE_ID  = "dockerImageId";  // Docker id, 64 character check sum for the ID - soon to be deprecated in favor of signature
final String IMAGE_SIGNATURE          = "dockerImageSignature";
final String HARBOR_IMAGE_SIGNATURE   = "harborImageSignature";

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

if (props['dockerRegistryName'] == null || props['dockerRegistryName'].size() == 0) {
    props['dockerRegistryName'] = 'index.docker.io'
}

String registry         = props['dockerRegistryName'].trim()
String componentName    = props['componentName'].trim()
String namingConvention = props['namingConvention']?:"hyphenated"
String registryType     = props['registryType']
String regexForTag      = props['regexForTag']?.trim()
def specificVersionList = props['version']?.split(',')*.trim()
String description      = props['description'];
String ucdUsername      = "PasswordIsAuthToken"
String ucdPassword      = String.format("{\"token\": \"%s\"}", System.getenv("AUTH_TOKEN"))
URI webUrl              = new URI(System.getenv("AH_WEB_URL"))
boolean allowVersionLinks = (props['allowVersionLinks']?:"false").toBoolean()

if (description == null) {
    
	description = "";
}

def awsTags
try {
    def client
    // IBM Container Registry
    if (registryType.equals('true')) {
        client = new IBMContainerRegistryClient(props)
    }
    // Artifactory
    else if (registryType.equals('artifactory')){
        client = new ArtifactoryClient(props)
    }
    // Amazon ECR
    else if (registryType.equals('amazon')){
        def awsClient = new AmazonECRClient(props)
        props['username'] = "AWS" //get from aws command instead
        props['password'] = awsClient.getDockerAuthToken()
        props['dockerRegistryName'] = awsClient.getRegistry()
        println "Found Docker registry: ${props['dockerRegistryName']}"
        awsTags = awsClient.getTags()
    }
	// Docker Trusted Registry
	else if (registryType.equals('dtr')){
		println("[Info] Creating DTR client")
		client = new DockerTrustedRegistryClient(props)
	}
    // Docker
    else {
        client = new RegistryClient(props)
    }

    ArrayList tags;
    Map tagIdLabels = [:]
    if (registryType.equals('amazon')) {
        awsTags.each { tag ->
			if(specificVersionList?.size()>1) {
				if(specificVersionList.contains(tag)){
					tagIdLabels.put(tag.imageTag, tag.imageDigest)
				}
			}else {
			
            if ( addOption(tag.imageTag, regexForTag) )
                tagIdLabels.put(tag.imageTag, tag.imageDigest)
			}
        }
    }
	else if (registryType.equals('dtr')){
		
		tags = client.getTags()
		tags.each { tag ->
			
			if(specificVersionList?.size()>1) {
				if(specificVersionList.contains(tag)){
				String id =   tag
				if (id) {
					tagIdLabels.put(tag, tag)
					}
				}
			}else {
			if ( addOption(tag, regexForTag) ) {
				String id =   tag
				if (id) {
					tagIdLabels.put(tag, tag)
					}
				}
			}
		}
	}
    else if (registryType.equals('harbor')) {
        tags = client.getTagsHarbor()

        tags.each { tag ->
            boolean shouldProcess = (specificVersionList?.size() > 1)
                    ? specificVersionList.contains(tag)
                    : addOption(tag, regexForTag)

            if (shouldProcess) {
                String id = client.getIdForTagHarbor(tag)
                String digest = client.getDigestForTagHarbor(tag)
                Map<String, String> labels = client.getLabelsForTagHarbor(tag) ?: [:]
                
                tagIdLabels.put(tag, digest)
                if (id) {
                    tagIdLabels.put(tag, [id, labels])
                }
            }
        }
    }
    else {
        tags = client.getTags()
        tags.each { tag ->
			if(specificVersionList?.size()>1) {
				if(specificVersionList.contains(tag)){
					String id = client.getIdForTag(tag)
					Map<String,String> labels = new HashMap<String,String>()
					labels.putAll(client.getLabelsForTag(tag) ?: new HashMap<String,String>())
					if (id) {
						tagIdLabels.put(tag, [id, labels])
					}
					}
				}else {
					if ( addOption(tag, regexForTag) ) {
						String id = client.getIdForTag(tag)
						Map<String,String> labels = new HashMap<String,String>()
						labels.putAll(client.getLabelsForTag(tag) ?: new HashMap<String,String>())
						if (id) {
							tagIdLabels.put(tag, [id, labels])
						}
					}
				}
        	}
    }

    ComponentClient componentClient = new ComponentClient(webUrl, ucdUsername, ucdPassword);
    VersionClient   versionClient;
    List<String>    existingVersions = componentClient.getComponentVersions(componentName, true);

    tagIdLabels.each {
        String tag = it.key
        def id     = it.value
        String shortId
		String dtrVersionName
		
        HashMap<String, String> labels
        // For Amazon ECR
        if (id.contains(":")) {
            shortId = id.split(":")[1].substring(0,7)
        }
		else if(registryType.equals('dtr')) {
			dtrVersionName = tag
		}
        // For all else
        else {
            id = it.value[0]
            // IBM Container Services
            if (id.contains(":")) {
                shortId = id.split(":")[1].substring(0,7)
            // For Docker and Artifactory
            }
            else {
                if(id.length() >= 7) {
                    shortId = id.substring(0,7)
                } else {
                    shortId = id
                }
            }
            labels  = it.value[1]
        }
        String versionName

        switch (namingConvention) {
            case "hyphenated":
                versionName = tag + " - " + shortId
                break
            case "space":
                versionName = tag + " " + shortId
                break
            case "tag_only":
                versionName = tag
                break
        }
        if (!existingVersions.contains(versionName)) {
            versionClient = new VersionClient(webUrl, ucdUsername, ucdPassword);
            
            String versionId
			if(registryType.equals('dtr')) {
				println "[Action] Creating new version, ${dtrVersionName}"
				versionId = versionClient.createVersion(componentName, dtrVersionName, description, true)
			}else {
				println "[Action] Creating new version, ${versionName}"
				versionId = versionClient.createVersion(componentName, versionName, description, true)
				versionClient.setVersionProperty(versionName, componentName, VERSION_DOCKER_IMAGE_TAG, tag, false)
			}
			
            apTool.setOutputProperty("VersionID", versionId);
            
            if (registryType.equals('amazon')) {
                versionClient.setVersionProperty(versionName, componentName, IMAGE_SIGNATURE, id, false)
            }
			else if(registryType.equals('dtr')) {
				println "[Info] DTR : Setting version property for ID"
				versionClient.setVersionProperty(dtrVersionName, componentName, VERSION_DOCKER_IMAGE_TAG, tag, false)
			}
            else if (registryType.equals('harbor')) {
                versionClient.setVersionProperty(versionName, componentName, HARBOR_IMAGE_SIGNATURE, id, false)
            }
            else {
                versionClient.setVersionProperty(versionName, componentName, VERSION_DOCKER_IMAGE_ID, id, false)
                labels.each { key, value ->
                    println "[Action] Adding property ${key}=${value} for version ${versionName}"
                    versionClient.setVersionProperty(versionName, componentName, key, value, false)
                }
                if (allowVersionLinks) {
                    labels.each { key, value ->
                        if (isValid(value)) {
                            println "[Action] Adding version link ${key}=${value} for version ${versionName}"
                            versionClient.addVersionLink(versionName, componentName, key, value)
                        }
                    }
                }
            }
            versionClient.markImportFinished(componentName, versionId);
            versionClient.client.close();
        }
        else {
            println "[Ok] Version, '${versionName}' already exists. Skipping..."
        }
    }
} catch(java.lang.Exception ex) {
    println("\n\n[Error] import version failed. \n")
    println(ex.getMessage())
    ex = null
    System.exit(1);
}
finally {
    apTool.storeOutputProperties();
}

println "[Ok] Import Complete"

// deals with regex when used
def addOption(def tag, def regex) {
    def option = false
    if (regex != null && regex.size() > 0 ) {
         def matcher = tag =~regex;
         if (matcher.find()) {
             println "Tag \"" + tag + "\" matched the regex \"" + regex + "\""
             option = true
         }
         else {
             println "Tag \"" + tag + "\" did not match the regex \"" + regex + "\""
             option = false
         }
     }
     else
         option = true
     return option
}

 public static boolean isValid(String url){
    try {
        new URL(url).toURI();
        return true;
    } catch (Exception e) {
        return false;
    }
}

