import java.nio.file.Files
import java.nio.file.Path as JPath
import java.nio.file.StandardCopyOption

import ch.raffael.doclets.pegdown.PegdownDoclet

import org.gradle.api.tasks.javadoc.internal.JavadocSpec
import org.gradle.jvm.internal.toolchain.JavaToolChainInternal
import org.gradle.jvm.platform.JavaPlatform
import org.gradle.jvm.platform.internal.DefaultJavaPlatform
import org.gradle.language.base.internal.compile.Compiler
// You should change this after releasing a new version of the Baku Toolkit. See the
// list of published versions at https://repo1.maven.org/maven2/io/v/baku-toolkit.
version = '0.10.2'
group = 'io.v'

def siteUrl = 'https://github.com/vanadium/java'
def gitUrl = 'https://github.com/vanadium/java.git'
def pkgDesc = 'Utilities for writing applications with distributed user interfaces'

apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.library'
apply plugin: 'com.github.dcendents.android-maven'
apply plugin: 'com.jfrog.bintray'
/*
You might have to download JDK8 and set JAVA8_HOME (or set the jdk to Java 8 via Project Structure).
For detailed instructions, see https://github.com/evant/gradle-retrolambda
 */
apply plugin: 'me.tatarka.retrolambda'

archivesBaseName = 'baku-toolkit'

android {
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
    compileSdkVersion 23
    buildToolsVersion "23.0.1"
    buildTypes {
        debug {
            multiDexEnabled true
        }
    }
    defaultConfig {
        minSdkVersion 21
    }
    packagingOptions {
        exclude 'META-INF/LICENSE.txt'
        exclude 'META-INF/NOTICE.txt'
    }
}

configurations {
    javadoc
}

dependencies {
    provided(
            /*
            https://projectlombok.org/setup/android.html
            Follow Android Studio instructions at the bottom of the page to install the Lombok
            Plugin.
             */
            'org.projectlombok:lombok:1.16.6',
            'org.slf4j:slf4j-api:1.7.12'
    )

    androidTestCompile 'org.slf4j:slf4j-android:1.7.12'

    testCompile(
            'org.mockito:mockito-core:1.10.19',
            'org.powermock:powermock-classloading-xstream:1.6.3',
            'org.powermock:powermock-module-junit4:1.6.3',
            'org.powermock:powermock-module-junit4-rule:1.6.3',
            'org.slf4j:slf4j-simple:1.7.12'
    )

    testCompile('org.powermock:powermock-api-mockito:1.6.3') {
        exclude module: 'mockito-all'
    }

    compile(
            /*
            Ideally this would be optional, but this unexpectedly becomes required if you touch
            the Baku CollectionBinding Builder, even if you don't actually try to bind to a
            RecyclerView.
             */
            'com.android.support:recyclerview-v7:23.0.1',
            'com.jakewharton.rxbinding:rxbinding:0.3.0',
            'commons-io:commons-io:2.4',
            'io.reactivex:rxandroid:1.1.0',
            'io.reactivex:rxjava:1.0.17',
            'io.reactivex:rxjava-async-util:0.21.0',
            'io.v:vanadium-android:1.11',
            'net.javacrumbs.future-converter:future-converter-guava-rxjava:0.3.0',
            'net.sourceforge.streamsupport:streamsupport:1.3.2',
            'org.robotninjas:fluent-futures:1.0'
    )

    compile fileTree(dir: 'libs', include: ['*.jar'])

    /*
    Word of caution: for local unit tests, Android log statements fail with
    UnsatisfiedLinkError (hence the slf4j-simple implementation for testCompile).

    Applications should include a suitable runtime binding, such as
    apk ('org.slf4j:slf4j-android:1.7.12')
    */

    //javadoc 'io.v:doclet:0.1.1'
    javadoc 'ch.raffael.pegdown-doclet:pegdown-doclet:1.2'
}

install {
    repositories.mavenInstaller {
        pom {
            project {
                packaging 'aar'

                name 'Baku Toolkit'
                description pkgDesc
                url siteUrl

                licenses {
                    license {
                        name 'New BSD License'
                        url 'https://github.com/vanadium/java/blob/master/LICENSE'
                        distribution 'repo'
                    }
                }
                scm {
                    connection gitUrl
                    url siteUrl
                }
                developers {
                    developer {
                        id 'vanadium'
                        name 'The Vanadium Contributors'
                        email 'vanadium-discuss@v.io'
                    }
                }
            }
        }
    }
}

task delombok {
    inputs.files android.sourceSets.main.java.srcDirs
    outputs.dir('build/delombok')

    android.libraryVariants.all { variant ->
        dependsOn variant.javaCompile
    }

    ant.taskdef(
            name: 'delombok',
            classname: 'lombok.delombok.ant.Tasks$Delombok',
            classpath: configurations.provided.asPath
    )

    doLast {
        // This must happen after compile because compile injects some generated classpath.
        ext.classpath = files(android.bootClasspath)
        android.libraryVariants.all { variant ->
            classpath += files(
                    variant.javaCompile.classpath.files,
                    variant.javaCompile.destinationDir // for io.v.baku.toolkit.R
            )
        }

        ant.delombok(
                from:inputs.files.asPath,
                to:outputs.files.asPath,
                classpath: classpath.asPath) {
            format(value: 'suppressWarnings:skip')
            format(value: 'danceAroundIdeChecks:skip')
            format(value: 'javaLangAsFQN:skip')
        }
    }
}

task javadoc(type: FullProcessingJavadoc) {
    source = delombok.outputs.files
    title "Baku Toolkit ${version} API"

    options {
        overview 'src/main/java/overview.md'
        docletpath = configurations.javadoc.files.asType(List)
        //doclet 'io.v.doclet.VDoclet'
        doclet 'ch.raffael.doclets.pegdown.PegdownDoclet'
        stylesheetFile = new File('lib/src/main/java/custom-styles.css')
        bottom new File('lib/src/main/java/bottom.html').text
        group 'API Surface', 'io.v.baku.toolkit'
        group 'Component Packages', 'io.v.baku.toolkit.*:io.v.rx:io.v.rx.*'
        //addStringOption 'defaultstart', 'io/v/baku/toolkit/BakuActivity.html'

        links (
                'http://docs.oracle.com/javase/8/docs/api/',
                'http://docs.guava-libraries.googlecode.com/git/javadoc/',
                'http://reactivex.io/RxJava/javadoc/',
                'http://www.atetric.com/atetric/javadoc/net.sourceforge.streamsupport/streamsupport/1.3.2/',
                'http://www.atetric.com/atetric/javadoc/org.robotninjas/fluent-futures/1.0/',
                'http://www.joda.org/joda-time/apidocs/'
        )
        linksOffline 'http://d.android.com/reference', "${android.sdkDirectory}/docs/reference"
    }

    if (JavaVersion.current().isJava8Compatible()) {
        // TODO(rosswang): Can we get rid of this?
        options.addStringOption('Xdoclint:none', '-quiet')
    }

    // This has to happen after the delombok task has actually run but before Javadoc generation.
    doFirst {
        classpath += delombok.classpath
    }
}

/**
 * https://groups.google.com/d/topic/gradle-dev/R83dy_6PHMc/discussion
 */
@ParallelizableTask
class FullProcessingJavadoc extends Javadoc {
    private Set<File> sourceDirs

    @Override
    public void setSource(Object sourceDirs) {
        this.sourceDirs = project.files(sourceDirs).files
        super.setSource(sourceDirs)
    }

    @Override
    protected void generate() {
        final File destinationDir = getDestinationDir();

        if (options.getDestinationDirectory() == null) {
            options.destinationDirectory(destinationDir);
        }

        options.classpath(new ArrayList<File>(getClasspath().getFiles()));

        if (!GUtil.isTrue(options.getWindowTitle()) && GUtil.isTrue(getTitle())) {
            options.windowTitle(getTitle());
        }
        if (options instanceof StandardJavadocDocletOptions) {
            StandardJavadocDocletOptions docletOptions = (StandardJavadocDocletOptions) options;
            if (!GUtil.isTrue(docletOptions.getDocTitle()) && GUtil.isTrue(getTitle())) {
                docletOptions.setDocTitle(getTitle());
            }
        }

        if (maxMemory != null) {
            final List<String> jFlags = options.getJFlags();
            final Iterator<String> jFlagsIt = jFlags.iterator();
            boolean containsXmx = false;
            while (!containsXmx && jFlagsIt.hasNext()) {
                final String jFlag = jFlagsIt.next();
                if (jFlag.startsWith("-Xmx")) {
                    containsXmx = true;
                }
            }
            if (!containsXmx) {
                options.jFlags("-Xmx" + maxMemory);
            }
        }

        Set<JPath> roots = sourceDirs.collect { it.toPath() } as Set
        Collection<JPath> sourcePaths = source.collect{ it.toPath() }
        Set<String> packages = new HashSet<>()

        sourcePaths.each { sourcePath ->
            JPath curRoot = roots.find { sourcePath.startsWith(it) }
            JPath rel = curRoot.relativize(sourcePath)

            if (sourcePath.parent.fileName as String == "doc-files") {
                // The Pegdown doclet seems to ignore doc-files entirely, so copy them explicitly.
                JPath dest = options.destinationDirectory.toPath().resolve(rel)
                Files.createDirectories(dest.parent)
                Files.copy(sourcePath, dest, StandardCopyOption.REPLACE_EXISTING)
            } else if (rel.parent != null) {
                packages += rel.parent.toString().replaceAll("/", ".")
            }
        }
        options.setSourceNames(packages as List);
        options.addStringsOption('sourcepath').value =
                roots.collect { it.toAbsolutePath() as String }

        // Pegdown won't copy the default stylesheet if we've specified a stylesheet of our own, but
        // ours is based off the default
        Files.copy(PegdownDoclet.class.getResourceAsStream("stylesheet.8.css"),
                options.destinationDirectory.toPath().resolve("stylesheet.css"),
                StandardCopyOption.REPLACE_EXISTING)

        executeExternalJavadoc();
    }

    private void executeExternalJavadoc() {
        JavadocSpec spec = new JavadocSpec();
        spec.setExecutable(executable);
        spec.setOptions(options);
        spec.setIgnoreFailures(!failOnError);
        spec.setWorkingDir(getProject().getProjectDir());
        spec.setOptionsFile(getOptionsFile());

        Compiler<JavadocSpec> generator = ((JavaToolChainInternal) getToolChain())
                .select(getPlatform()).newCompiler(JavadocSpec.class);

        generator.execute(spec);
    }

    private static JavaPlatform getPlatform() {
        return DefaultJavaPlatform.current();
    }
}

task sourcesJar(type: Jar) {
    from delombok
    classifier 'sources'
}

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

artifacts {
    archives javadocJar
    archives sourcesJar
}

tasks.bintrayUpload.dependsOn(tasks.install)

bintray {
    user = project.properties.bintrayUsername
    key = project.properties.bintrayApiKey

    configurations = ['archives']

    pkg {
        desc = pkgDesc
        websiteUrl = siteUrl
        vcsUrl = gitUrl
        repo = group
        name = archivesBaseName
        licenses = ['BSD New']
        userOrg = 'vanadium'
        publish = true

        version {
            name = project.version
            gpg {
                sign = true
            }
        }
    }
}
