/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

/**
 * The sole purpose of this sub-project is to produce a shaded package for the vertx-client. Currently,
 * the shadow plugin has some limitations when producing a non-shaded and shaded versions of the jar.
 */

import com.github.jengelman.gradle.plugins.shadow.transformers.CacheableTransformer
import com.github.jengelman.gradle.plugins.shadow.transformers.Transformer
import com.github.jengelman.gradle.plugins.shadow.transformers.TransformerContext
import shadow.org.apache.tools.zip.ZipEntry
import shadow.org.apache.tools.zip.ZipOutputStream

import java.nio.file.Paths

plugins {
    id('java-library')
    id('maven-publish')
    id('com.github.johnrengelman.shadow') version '6.1.0'
}

group 'org.apache.cassandra.sidecar'
version project.version

sourceCompatibility = 1.8

configurations {
    all*.exclude(group: 'ch.qos.logback')
}

dependencies {
    shadow(group: 'org.slf4j', name: 'slf4j-api', version: "${project.slf4jVersion}")
    api(project(':vertx-client'))

    testImplementation 'org.junit.jupiter:junit-jupiter:5.9.1'
    testImplementation(project(path: ':vertx-client-shaded', configuration: 'shadow'))
}

tasks.named('test') {
    // Use JUnit Platform for unit tests.
    useJUnitPlatform()
    reports {
        junitXml.enabled = true
        def destDir = Paths.get(rootProject.rootDir.absolutePath, "build", "test-results", "vertx-client-shaded").toFile()
        println("Destination directory for vertx-client-shaded tests: ${destDir}")
        junitXml.destination = destDir
        html.enabled = true
    }
}

// Relocating a Package
shadowJar {
    archiveClassifier.set('')
    // Our use of Jackson should be an implementation detail - shade everything so no matter what
    // version of Jackson is available in the classpath we don't break consumers of the client
    relocate 'com.fasterxml.jackson', 'o.a.c.sidecar.client.shaded.com.fasterxml.jackson'
    relocate 'io.netty', 'o.a.c.sidecar.client.shaded.io.netty'
    relocate 'io.vertx', 'o.a.c.sidecar.client.shaded.io.vertx'
    relocate 'META-INF/native/libnetty', 'META-INF/native/libo_a_c_sidecar_client_shaded_netty'
    relocate 'META-INF/versions/11/io/vertx', 'META-INF/versions/11/o/a/c/sidecar/client/shaded/io/vertx'
    transform(NettyResourceTransformer.class)
    mergeServiceFiles()

    dependencies {
        exclude(dependency('org.slf4j:.*:.*'))
    }
}

publishing {
    publications {
        shadow(MavenPublication) { publication ->
            project.shadow.component(publication)

            groupId project.group
            artifactId "vertx-client-all"
            version System.getenv("CODE_VERSION") ?: "${version}"
        }
    }
}

/**
 * A Transformer which updates the Netty JAR META-INF/ resources to accurately
 * reference shaded class names.
 */
@CacheableTransformer
class NettyResourceTransformer implements Transformer {

    // A map of resource file paths to be modified
    private Map<String, String> resources = [:]

    @Override
    boolean canTransformResource(FileTreeElement fileTreeElement) {
        fileTreeElement.name.startsWith("META-INF/native-image/io.netty")
    }

    @Override
    void transform(TransformerContext context) {
        String updatedPath = context.path.replace("io.netty", "o.a.c.sidecar.client.shaded.io.netty")
        String updatedContent = context.is.getText().replace("io.netty", "o.a.c.sidecar.client.shaded.io.netty")
        resources.put(updatedPath, updatedContent)
    }

    @Override
    boolean hasTransformedResource() {
        resources.size() > 0
    }

    @Override
    void modifyOutputStream(ZipOutputStream jos, boolean preserveFileTimestamps) {
        for (resourceEntry in resources) {
            ZipEntry entry = new ZipEntry(resourceEntry.key)
            entry.time = TransformerContext.getEntryTimestamp(preserveFileTimestamps, entry.time)

            jos.putNextEntry(entry)
            jos.write(resourceEntry.value.getBytes())
            jos.closeEntry()
        }
    }
}
