/*
 1. must add the following classpath in root build.gradle
 classpath "com.github.dcendents:android-maven-gradle-plugin:2.1"
 classpath "com.jfrog.bintray.gradle:gradle-bintray-plugin:1.8.4"

 2. add bintrayUser, bintrayKey in root local.properties

 3. copy the file to the directory of gradle, and apply the file in the module
 apply from: "${rootDir.path}/gradle/publish.gradle"
 publish {
    name = "UtilCode"
    groupId = "com.blankj"
    artifactId = "utilcode"
    version = "xx.xx"
    website = "https://github.com/Blankj/AndroidUtilCode"
 }

 4. execute following command to publish
 ./gradlew bintrayUpload    -> upload to bintray
 ./gradlew mavenLocal       -> upload to local maven
*/

apply plugin: "com.github.dcendents.android-maven"
apply plugin: "com.jfrog.bintray"

extensions.create('publish', PublishExtension)

afterEvaluate {
    def ext = project['publish'] as PublishExtension
    loadBintray(ext)
    configMaven(project, ext)
    configBintray(project, ext)
    configJavadoc(project, ext)
}

private void loadBintray(PublishExtension ext) {
    Properties properties = new Properties()
    File localPropertiesFile = project.rootProject.file("local.properties");
    if (localPropertiesFile.exists()) {
        properties.load(localPropertiesFile.newDataInputStream())
        ext.bintrayUser = properties.getProperty("bintrayUser")
        ext.bintrayKey = properties.getProperty("bintrayKey")
    }
}

def configMaven(Project project, PublishExtension ext) {
    project.group = ext.groupId
    project.version = ext.version

    project.install {
        repositories.mavenInstaller {
            configPom(pom, ext)
        }
    }

    project.tasks.create("mavenLocal", Upload) {
        group("publishing")
        configuration = project.configurations.archives

        repositories.mavenDeployer {
            repository(url: uri("${project.rootDir.path}/mavenLocal"))
            configPom(pom, ext)
        }

        doFirst {
            ext.check(false)
        }
    }

    project.tasks.findByName("bintrayUpload").doFirst {
        ext.check(true)
    }
}

def configPom(pom, PublishExtension ext) {
    pom.project {
        name ext.name
        groupId ext.groupId
        artifactId ext.artifactId
        version ext.version
        packaging isAndroid() ? "aar" : "jar"
        description ext.name
        url ext.website

        scm {
            url ext.website
            connection ext.website
            developerConnection ext.website + ".git"
        }

        licenses {
            license {
                name 'The Apache Software License, Version 2.0'
                url 'http://www.apache.org/licenses/LICENSE-2.0.txt'
            }
        }

        developers {
            developer {
                id ext.bintrayUser
                name ext.bintrayUser
            }
        }
    }

    pom.whenConfigured {
        // 检测 module 中的 dependencies 是否有源码依赖
        // 如果是源码依赖，而且没有在 config 中配置 remotePath，那么发布到仓库，其他地方依赖该库时会找不到源码的那个库
        it.dependencies.findAll { dep -> dep.version == "unspecified" }.collect { dep ->
            DepConfig config = Config.depConfig.get(dep.artifactId)
            if (config == null || config.version == null) {
                // 源码依赖而且没有在 config 中配置 remotePath，直接报错
                System.err.println("The module of <" + dep.artifactId + "> should publish to maven first.")
                throw new RuntimeException()
            }
            dep.groupId = config.groupId
            dep.version = config.version
            // 源码依赖，但配置了 remotePath，让 pom 中写入 remotePath
            GLog.l("Please check <${dep.groupId}:${dep.artifactId}:${dep.version}> is published.")
        }
    }
}

def configBintray(Project project, PublishExtension ext) {
    project.bintray {
        user = ext.bintrayUser
        key = ext.bintrayKey
        configurations = ['archives']
        override = false
        publish = true
        pkg {
            repo = "maven"
            name = ext.name
            websiteUrl = ext.website
            vcsUrl = ext.website + '.git'
            licenses = ["Apache-2.0"]
        }
    }
}

private void configJavadoc(Project project, PublishExtension ext) {
    if (isAndroid()) {
        // This generates sources.jar
        task sourcesJar(type: Jar) {
            classifier = 'sources'
            from android.sourceSets.main.java.source
        }

        task javadoc(type: Javadoc) {
            source = android.sourceSets.main.java.source
            classpath += configurations.compile
            classpath += project.files(android.getBootClasspath().join(File.pathSeparator))
        }

        task javadocJar(type: Jar, dependsOn: javadoc) {
            classifier = 'javadoc'
            from javadoc.destinationDir
        }
    } else {
        task sourcesJar(type: Jar, dependsOn: classes) {
            classifier = 'sources'
            from sourceSets.main.allSource
        }

        task javadocJar(type: Jar, dependsOn: javadoc) {
            classifier = 'javadoc'
            from javadoc.destinationDir
        }
    }

    if (project.hasProperty("kotlin")) {
        // Disable creating javadocs
        project.tasks.withType(Javadoc) {
            enabled = false
        }
    }

    javadoc {
        options {
            encoding "UTF-8"
            charSet 'UTF-8'
            author true
            version ext.version
            links "http://docs.oracle.com/javase/7/docs/api"
            title "${ext.name} ${ext.version}"
        }
    }

    artifacts {
        archives javadocJar
        archives sourcesJar
    }
}

def isAndroid() {
    return project.getPlugins().hasPlugin('com.android.application') ||
            project.getPlugins().hasPlugin('com.android.library')
}

class PublishExtension {
    String name
    String groupId
    String artifactId
    String version
    String website

    String bintrayUser
    String bintrayKey

    void check(boolean isBintray) {
        checkField(name, "name")
        checkField(groupId, "groupId")
        checkField(artifactId, "artifactId")
        checkField(version, "version")
        checkField(website, "website")

        if (isBintray) {
            if (isBintrayEmpty()) {
                throw new NullPointerException("U should set bintrayUser and bintrayKey in local.properties")
            }
        }
    }

    boolean isBintrayEmpty() {
        return isEmpty(bintrayUser) || isEmpty(bintrayKey)
    }

    static void checkField(String field, String fieldName) {
        if (isEmpty(field)) {
            throw new NullPointerException("$fieldName is empty!!")
        }
    }

    static boolean isEmpty(String str) {
        return str == null || str.length() == 0
    }
}