import org.gradle.api.artifacts.ivy.IvyModuleDescriptor
import org.gradle.model.Mutate

/*
 * Copyright 2014 the original author or authors.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

repositories {
    ivy {
        url "file://${projectDir}/repo"
    }
}

// Set up the status scheme so that "experimental" is a valid status for "org.sample" artifacts
dependencies {
    components {
        all { ComponentMetadataDetails details ->
            if (details.id.group == "org.sample") {
                details.statusScheme = ["experimental", "integration", "milestone", "release"]
            }
        }
    }
}

configurations {
    rejectConfig {
        resolutionStrategy {
            componentSelection {
                // Accept the highest version matching the requested version that isn't '1.5'
                all { ComponentSelection selection ->
                    if (selection.candidate.group == 'org.sample' && selection.candidate.module == 'api' && selection.candidate.version == '1.5') {
                        selection.reject("version 1.5 is broken for 'org.sample:api'")
                    }
                }
            }
        }
    }
}

dependencies {
    rejectConfig "org.sample:api:1.+"
}

task printRejectConfig {
    doLast {
        configurations.rejectConfig.each { println "Resolved: ${it.name}" }
    }
}

configurations {
    metadataRulesConfig {
        resolutionStrategy {
            componentSelection {
                // Reject any versions with a status of 'experimental'
                all { ComponentSelection selection, ComponentMetadata metadata ->
                    if (selection.candidate.group == 'org.sample' && metadata.status == 'experimental') {
                        selection.reject("don't use experimental candidates from 'org.sample'")
                    }
                }
                // Accept the highest version with either a "release" branch or a status of 'milestone'
                withModule('org.sample:api') { ComponentSelection selection, IvyModuleDescriptor descriptor, ComponentMetadata metadata ->
                    if (descriptor.branch != "release" && metadata.status != 'milestone') {
                        selection.reject("'org.sample:api' must have testing branch or milestone status")
                    }
                }
            }
        }
    }
}

dependencies {
    metadataRulesConfig "org.sample:api:1.+"
    metadataRulesConfig "org.sample:lib:+"
}

task printMetadataRulesConfig {
    doLast {
        configurations.metadataRulesConfig.each { println "Resolved: ${it.name}" }
    }
}

configurations {
    targetConfig {
        resolutionStrategy {
            componentSelection {
                withModule("org.sample:api") { ComponentSelection selection ->
                    if (selection.candidate.version == "1.5") {
                        selection.reject("version 1.5 is broken for 'org.sample:api'")
                    }
                }
            }
        }
    }
}

dependencies {
    targetConfig "org.sample:api:1.+"
}

task printTargetConfig {
    doLast {
        configurations.targetConfig.each { println "Resolved: ${it.name}" }
    }
}

class RejectTestBranch {
    @Mutate
    void evaluateRule(ComponentSelection selection, IvyModuleDescriptor ivy) {
        if (ivy.branch == "test") {
            selection.reject("reject test branch")
        }
    }
}

configurations {
    ruleSourceConfig {
        resolutionStrategy {
            componentSelection {
                all new RejectTestBranch()
            }
        }
    }
}

dependencies {
    ruleSourceConfig "org.sample:api:1.+"
}

task printRuleSourceConfig {
    doLast {
        configurations.ruleSourceConfig.each { println "Resolved: ${it.name}" }
    }
}

configurations {
    sampleConfig {
        resolutionStrategy {
            componentSelection {
                withModule("org.sample:api") { ComponentSelection selection ->
                    // Veto everything except patch releases
                    if (selection.candidate.version.matches('\\d+.\\d+\\.\\d+')) {
                        logger.lifecycle("** Accepted version: ${selection.candidate.version} **")
                    } else {
                        logger.lifecycle("Rejected version: ${selection.candidate.version}")
                        selection.reject("Version is broken")
                    }
                }
            }
        }
    }
}

dependencies {
    sampleConfig group: 'org.sample', name: 'api', version: '1+'
}

task resolveConfiguration {
    doLast {
        configurations.sampleConfig.files.each { println it }
    }
}
