buildscript {
    dependencies {
        classpath 'com.google.guava:guava:30.0-android'
    }
}

plugins {
    id "java-library"
    id "java-test-fixtures"
    id "maven-publish"

    id "me.champeau.gradle.japicmp"
    id "me.champeau.jmh"
    id "ru.vyarus.animalsniffer"
}

import static java.nio.charset.StandardCharsets.US_ASCII;

import com.google.common.primitives.Bytes;

description = 'gRPC: Core'

dependencies {
    api project(':grpc-api')
    implementation libraries.gson,
            libraries.android.annotations,
            libraries.animalsniffer.annotations,
            libraries.errorprone.annotations,
            libraries.guava,
            libraries.perfmark.api
    testFixturesApi libraries.junit
    testFixturesImplementation libraries.guava,
            libraries.mockito.core,
            libraries.truth,
            project(':grpc-testing')
    testImplementation testFixtures(project(':grpc-context')),
            testFixtures(project(':grpc-api')),
            project(':grpc-testing'),
            project(':grpc-grpclb')
    testImplementation (libraries.guava.testlib) {
        exclude group: 'junit', module: 'junit'
    }

    testRuntimeOnly project(':grpc-census')

    jmh project(':grpc-testing')

    signature libraries.signature.java
    signature libraries.signature.android
}

tasks.named("javadoc").configure {
    exclude 'io/grpc/internal/**'
    exclude 'io/grpc/inprocess/Internal*'
    // Disabled until kinda stable.
    exclude 'io/grpc/perfmark/**'
}

animalsniffer {
    // Don't check sourceSets.jmh
    sourceSets = [
        sourceSets.main,
        sourceSets.test
    ]
}

components.java.withVariantsFromConfiguration(configurations.testFixturesApiElements) { skip() }
components.java.withVariantsFromConfiguration(configurations.testFixturesRuntimeElements) { skip() }

import net.ltgt.gradle.errorprone.CheckSeverity

def replaceBytes(byte[] haystack, byte[] needle, byte[] replacement) {
    int i = Bytes.indexOf(haystack, needle);
    assert i != -1;
    byte[] result = new byte[haystack.length - needle.length + replacement.length];
    System.arraycopy(haystack, 0, result, 0, i);
    System.arraycopy(replacement, 0, result, i, replacement.length);
    System.arraycopy(haystack, i + needle.length, result, i + replacement.length, haystack.length - i - needle.length);
    return result;
}

def bigEndianShortBytes(int value) {
    return [value >> 8, value & 0xFF] as byte[];
}

def replaceConstant(File file, String needle, String replacement) {
    // CONSTANT_Utf8_info. https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4.7
    byte[] needleBytes = Bytes.concat(
        [1] as byte[], bigEndianShortBytes(needle.length()), needle.getBytes(US_ASCII));
    byte[] replacementBytes = Bytes.concat(
        [1] as byte[], bigEndianShortBytes(replacement.length()), replacement.getBytes(US_ASCII));
    file.setBytes(replaceBytes(file.getBytes(), needleBytes, replacementBytes));
}

plugins.withId("java") {
    tasks.named("compileJava").configure {
        doLast {
            // Replace value of Signature Attribute.
            // https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.7.9
	    //
	    // Have new compilations compile against a public class, without breaking the internal
	    // ABI for the moment. After giving users some time to recompile, this should be removed
	    // and #7211 can continue. When this is removed, at the very least the generics need to
	    // be changed to avoid <? extends io.grpc.internal.*>.
            project.replaceConstant(
                destinationDirectory.file(
                    "io/grpc/internal/AbstractManagedChannelImplBuilder.class").get().getAsFile(),
                "<T:Lio/grpc/internal/AbstractManagedChannelImplBuilder<TT;>;>Lio/grpc/ManagedChannelBuilder<TT;>;",
                "<T:Lio/grpc/ManagedChannelBuilder<TT;>;>Lio/grpc/ManagedChannelBuilder<TT;>;");
            project.replaceConstant(
                destinationDirectory.file(
                    "io/grpc/internal/AbstractServerImplBuilder.class").get().getAsFile(),
                "<T:Lio/grpc/internal/AbstractServerImplBuilder<TT;>;>Lio/grpc/ServerBuilder<TT;>;",
                "<T:Lio/grpc/ServerBuilder<TT;>;>Lio/grpc/ServerBuilder<TT;>;");
        }
    }
}

tasks.register("versionFile") {
    doLast {
        new File(buildDir, "version").write("${project.version}\n")
    }
}
