import groovy.util.logging.Slf4j
import java.util.regex.Matcher
import java.util.regex.Pattern
import org.commonjava.maven.atlas.ident.ref.ProjectVersionRef
import org.commonjava.maven.atlas.ident.ref.SimpleProjectVersionRef
import org.commonjava.maven.ext.common.ManipulationException
import org.commonjava.maven.ext.common.model.Project
import org.commonjava.maven.ext.core.ManipulationSession
import org.commonjava.maven.ext.core.groovy.BaseScript
import org.commonjava.maven.ext.core.groovy.InvocationStage
import org.commonjava.maven.ext.core.groovy.PMEBaseScript
import org.commonjava.maven.ext.core.groovy.PMEInvocationPoint
import org.commonjava.maven.ext.core.state.RESTState
import org.commonjava.maven.ext.io.rest.Translator

/**
*
* version.com.redhat.ba property sets to the final rhba version decided by PME 
* and taken from DA service at LAST invocation stage.
* The value is taken from org.kie.rhba:rhpam
*
**/
@PMEInvocationPoint(invocationPoint = InvocationStage.LAST)
@PMEBaseScript BaseScript pme
@Slf4j
public class ForceComRedhatBaVersionLastExecutor {

    BaseScript pme
    Project project

    def execute() {
        def String versionComRedhatBaProperty = 'version.com.redhat.ba'
        def String microVersionComRedhatBaProperty = 'micro.version.com.redhat.ba'

        def Pattern versionPattern = Pattern.compile("^(\\d+\\.)?(\\d+\\.)?(\\*|\\d+)")
        def Matcher matcher = versionPattern.matcher(project.getVersion())
        def Boolean matches = false
        while (matcher.find()) {
            matches = true
            def String versionWithoutSuffix = matcher.group()

            // Set the 'version.com.redhat.ba' property value
            setPropertyValue("org.kie.rhba:rhpam:" + versionWithoutSuffix, "rhpam", versionComRedhatBaProperty)

            // Set the 'version.com.redhat.ba' property value
            project.getModel().addProperty(microVersionComRedhatBaProperty, versionWithoutSuffix)
            log.info("property {} set to {} ", microVersionComRedhatBaProperty, versionWithoutSuffix)
        }
        if(!matches) {
            throw new RuntimeException("The project version " + project.getVersion() + " does not match with the expected pattern")
        }
    }

    private String setPropertyValue(String gavString, String gavName, String property) {
        ProjectVersionRef gavVersionRef = SimpleProjectVersionRef.parse(gavString)
        def gavVersion = getGavVersion(gavVersionRef)
        log.info("{} version retrieved {} ", gavName, gavVersion)
        project.getModel().addProperty(property, gavVersion)
        log.info("Property {} set to {} ", property, gavVersion)
    }

    private String getGavVersion(ProjectVersionRef gav) {
        List<ProjectVersionRef> source = new ArrayList();
        source.add(gav);
        source.add(pme.getGAV());
        Map<ProjectVersionRef, String> restResult = this.getRESTAPI().translateVersions(source);
        String targetBuild = (String) restResult.get(gav);
        if (targetBuild == null) {
            log.error("REST result was {}", restResult);
            throw new ManipulationException("Multiple results returned; unable to get version.", new String[0]);
        } else {
            return targetBuild;
        }
    }

    private Translator getRESTAPI() throws ManipulationException {
        RESTState rs = (RESTState) ((ManipulationSession) pme.getSession()).getState(RESTState.class);
        return rs.getVersionTranslator();
    }    
}

def ForceComRedhatBaVersionLastExecutor forceComRedhatBaVersionLast = new ForceComRedhatBaVersionLastExecutor(pme: pme, project: pme.getProject())
forceComRedhatBaVersionLast.execute()