buildscript {
    repositories {
        mavenCentral()
    }

    dependencies {
        classpath 'com.android.tools.build:gradle:1.2.3'
        classpath 'com.jakewharton.sdkmanager:gradle-plugin:0.12.0'
    }
}

apply plugin: 'android-sdk-manager'
apply plugin: 'com.android.library'
apply plugin: 'maven-publish'
apply plugin: 'wrapper'

android {
    buildToolsVersion '21.1.2'
    compileSdkVersion 19

    defaultConfig {
        minSdkVersion 19
    }

    lintOptions {
        abortOnError false
    }

    defaultConfig {
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
}

repositories {
    mavenCentral()
}

dependencies {
    compile project(':lib')
    androidTestCompile 'junit:junit:4.12'
    androidTestCompile 'com.google.truth:truth:0.25'
    // This dependency exists only to work around an issue in the sdkmanager plugin v0.12.0. This
    // should be fixed when http://git.io/vIXec is checked in and a release is made.
    androidTestCompile('com.android.support:support-v4:21.0.0')
    androidTestCompile('com.android.support.test:runner:0.3') {
        exclude group: 'junit'  // junit:junit-dep conflicts with junit:unit
    }
}

public static isDarwin() {
    return getOS().contains("os x")
}

public static isLinux() {
    return getOS().contains("linux")
}

public static isAmd64() {
    return getArch().contains("x86_64") || getArch().contains("amd64")
}

public static getArch() {
    return System.properties['os.arch'].toLowerCase()
}

public static getOS() {
    return System.properties['os.name'].toLowerCase()
}

def jiriRoot = VanadiumEnvironment.getVanadiumEnvironment().jiriRoot.getAbsolutePath()

class VanadiumEnvironment {
    File jiriRoot;
    File jiriBin;
    File thirdPartyGoBinDir;

    public static getVanadiumEnvironment() {
        VanadiumEnvironment result = new VanadiumEnvironment()

        if (!System.getenv().containsKey('JIRI_ROOT')) {
            throw new InvalidUserDataException("JIRI_ROOT is not set. "
                    + "Please follow the Vanadium installation instructions at "
                    + "https://github.com/vanadium/docs/blob/master/installation.md")
        }

        result.jiriRoot = new File(System.getenv()['JIRI_ROOT'])
        result.jiriBin = new File(result.jiriRoot, ['devtools', 'bin', 'jiri'].join(File.separator))
        if (!result.jiriBin.exists() || !result.jiriBin.isFile() || !result.jiriBin.canExecute()) {
            throw new InvalidUserDataException(
                    result.jiriBin.toString() + " does not exist or is not an executable file. "
                    + "Please follow the Vanadium installation instructions at "
                    + "https://github.com/vanadium/docs/blob/master/installation.md")
        }

        result.thirdPartyGoBinDir = new File(result.jiriRoot,
                ['third_party', 'android', 'go', 'bin'].join(File.separator))
        def thirdPartyGoBin = new File(result.thirdPartyGoBinDir, 'go')
        if (!thirdPartyGoBin.exists() || !thirdPartyGoBin.isFile() || !thirdPartyGoBin.canExecute()) {
            throw new InvalidUserDataException(
                    thirdPartyGoBin.toString() + " does not exist or is not an executable file. "
                    + "You probably didn't install the android profile. Try running\n\n"
                    + "jiri profile install android\n\nand then try building again.")
        }

        def syncbaseOutputDir = new File(result.jiriRoot,
                ['third_party', 'cout', 'android_arm', 'leveldb'].join(File.separator))
        if (!syncbaseOutputDir.exists() || !syncbaseOutputDir.isDirectory()) {
            throw new InvalidUserDataException(
                    syncbaseOutputDir.toString() + " does not exist or is not a directory. "
                    + "You probably didn't install the android syncbase profile. Try running\n\n"
                    + "GOOS=android GOARCH=arm jiri profile install syncbase"
                    + "\n\nand then try building again"
            )
        }

        return result
    }
}

task checkVanadiumEnvironment {
    VanadiumEnvironment.getVanadiumEnvironment()
    if (!isAmd64()) {
        throw new InvalidUserDataException("Android Vanadium builds only enabled on amd64 "
                + "architectures, not: " + getArch())
    }
    if (!isLinux() && !isDarwin()) {
        throw new InvalidUserDataException("Android Vanadium builds only enabled on "
                + "linux/darwin systems, not: " + getOS())
    }
}

task goBuildVanadiumLib(type: Exec, dependsOn: checkVanadiumEnvironment) {
    def env = VanadiumEnvironment.getVanadiumEnvironment()
    def existingPath = System.getenv('PATH')
    if (existingPath == null) {
        existingPath = ""
    }

    environment 'JIRI_PROFILE': 'android'
    environment 'PATH': [env.thirdPartyGoBinDir.getAbsolutePath(), existingPath].join(File.pathSeparator)

    commandLine env.jiriBin.getAbsolutePath(), 'go', 'install',
            '-buildmode=c-shared', '-v', '-tags', 'android', 'v.io/x/jni/main'
}

// Copy the shared library to its ultimate destination.
task copyVanadiumLib(type: Copy, dependsOn: goBuildVanadiumLib) {
    from jiriRoot + '/release/go/pkg/android_arm/v.io/x/jni'
    into 'src/main/jniLibs/armeabi-v7a'
    include 'main.a'
    rename 'main.a', 'libv23.so'
}

clean {
    delete 'src/main/jniLibs/armeabi-v7a/libv23.so'
}

task sourceJar(type: Jar) {
    from android.sourceSets.main.java.srcDirs
    classifier "source"
}

publishing {
    publications {
        androidLibrary(MavenPublication) {
            groupId 'io.v'
            artifactId 'vanadium-android'
            version '0.1-SNAPSHOT'
            artifact(sourceJar)
            artifact("$buildDir/outputs/aar/android-lib-release.aar")
        }
    }
    repositories {
        maven {
            credentials {
                username 'admin'
                password 'admin123'
            }
            url "http://srdjan.mtv:8081/nexus/content/repositories/test_repo"
        }
    }
}

wrapper {
    gradleVersion = '2.4'
}

tasks.'preBuild'.dependsOn(copyVanadiumLib)
tasks.'publish'.dependsOn(tasks.'assemble')
