/*
 * 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
 *
 *   https://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.
 */

import org.apache.plc4x.java.DefaultPlcDriverManager
import org.apache.maven.artifact.Artifact
import org.apache.plc4x.java.api.metadata.Option

def static outputOptions(List<Option> options, String prefix, PrintStream printStream) {
    options.each {option->
        def name = prefix?"$prefix.$option.key":option.key
        // Convert java line-breaks into asciidoctor line-breaks.
        def description = option.description.replaceAll('\n', " +\n")
        option.since.ifPresent {
            description += " +\n*Since: " + option.since.get() + "*"
        }
        printStream.println "|`$name` |$option.type |${option.defaultValue.orElse(' ')}|${option.required?'required':''} |$description"
    }
}

// Build a classloader that can access the projects classpath (read from dependencies)
ClassLoader moduleClassloader
try {
    Set<Artifact> artifacts = project.getArtifacts()
    List<URL> classpathElements = new ArrayList<>(artifacts.size() + 1)
    // Add the normal class output (needed for embedded schemas)
    classpathElements.add(new File(project.getBuild().getOutputDirectory()).toURI().toURL())
    // Add all the other artifacts (no matter what scope)
    for (Artifact artifact : artifacts) {
        classpathElements.add(artifact.getFile().toURI().toURL())
    }
    moduleClassloader = new URLClassLoader(classpathElements.toArray(new URL[0]), this.class.getClassLoader())
} catch (MalformedURLException e) {
    throw new Exception(
        "Error creating classloader for loading message format schema from module dependencies", e);
}
Thread.currentThread().setContextClassLoader(moduleClassloader)

// Create a driver manager instance, that is using our custom built classloader.
def plcDriverManager = new DefaultPlcDriverManager(moduleClassloader)

// Process all driver information.
for (final def protocolCode in plcDriverManager.getProtocolCodes()) {
    def outputFile = new File(project.getBasedir(), "../../../website/asciidoc/modules/users/partials/" + protocolCode + ".adoc")
    // In order to re-generate this file, make sure it doesn't exist.
    if(outputFile.exists()) {
        outputFile.delete()
    }
    // Make sure all directories exist.
    if(!outputFile.parentFile.exists()) {
        outputFile.parentFile.mkdirs()
    }
    def printStream = new PrintStream(outputFile)

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

    def driver = plcDriverManager.getDriver(protocolCode)
    printStream.println "[cols=\"2,2a,2a,2a,4a\"]\n" +
        "|===\n" +
        "|Name |Type |Default Value |Required |Description"
    printStream.println "|Name 4+|" + driver.protocolName
    printStream.println "|Code 4+|`" + protocolCode + "`"
    printStream.println "|Maven Dependency 4+|"
    // Find out which jar the driver was loaded from.
    def resource = moduleClassloader.getResource(driver.class.name.replace('.', '/') + ".class")
    def uriString = resource.toExternalForm()
    var moduleName = uriString.substring(uriString.indexOf("plc4j-driver-"), uriString.indexOf("/", uriString.indexOf("plc4j-driver-")))
    printStream.println "\n" +
        "[subs=attributes+]\n" +
        "----\n" +
        "<dependency>\n" +
        "  <groupId>org.apache.plc4x</groupId>\n" +
        "  <artifactId>" + moduleName + "</artifactId>\n" +
        "  <version>{page-component-version}</version>\n" +
        "</dependency>\n" +
        "----"
    if(driver.metadata.defaultTransportCode.isPresent()) {
        printStream.println "|Default Transport 4+|`" + driver.metadata.defaultTransportCode.get() + "`"
    }
    printStream.println "|Supported Transports 4+|"
    for (final def transportCode in driver.metadata.supportedTransportCodes) {
        // TODO: Make it output stuff like the "default port" for UDP and TCP
        printStream.println " - `" + transportCode + "`"
    }
    printStream.println "5+|Config options:"

    // Output the configuration options of the driver itself.
   driver.metadata.protocolConfigurationOptionMetadata.map {outputOptions(it.options, null, printStream)}

    // Output the configuration options of the transports the driver supports.
    if(!driver.metadata.supportedTransportCodes.empty) {
        printStream.println "5+|Transport config options:"
        for (final def transportCode in driver.metadata.supportedTransportCodes) {
            printStream.println "5+|\n+++\n" +
                "<h4>$transportCode</h4>\n" +
                "+++"
            driver.metadata.getTransportConfigurationOptionMetadata(transportCode).map {
                outputOptions(it.options, transportCode, printStream)
            }
        }
    }

    printStream.println "|==="

    printStream.close()
}