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.0'
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.10',
            '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/'
        )
        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
            }
        }
    }
}
