// Copyright Yahoo. Licensed under the terms of the Apache 2.0 license. See LICENSE in the project root.
package ai.vespa.hosted.plugin;

import com.yahoo.component.Version;
import com.yahoo.component.Vtag;
import com.yahoo.text.XML;
import org.apache.maven.plugins.annotations.Mojo;
import org.apache.maven.plugins.annotations.Parameter;
import org.w3c.dom.Element;

import java.io.File;
import java.io.IOException;
import java.io.UncheckedIOException;
import java.nio.file.Files;
import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.OptionalInt;

/**
 * Finds the Vespa version to compile against, for a hosted Vespa application.
 *
 * @author jonmv
 */
@Mojo(name = "compileVersion")
public class CompileVersionMojo extends AbstractVespaMojo {

    @Parameter(property = "outputFile", defaultValue = "target/vespa.compile.version")
    private String outputFile;

    @Override
    protected void doExecute() throws IOException {
        Path output = Paths.get(outputFile).toAbsolutePath();
        OptionalInt allowMajor = majorVersion(new File(project.getBasedir(), "src/main/application/deployment.xml").toPath());
        allowMajor.ifPresent(major -> getLog().info("Allowing only major version " + major + "."));

        Version compileVersion = Version.fromString(controller.compileVersion(id, allowMajor));
        if (compileVersion.isAfter(Vtag.currentVersion))
            throw new IllegalStateException("parent version (" + Vtag.currentVersion.toFullString() + ") should be at least as " +
                                            "high as the Vespa version to compile against (" + compileVersion.toFullString() + ")");

        getLog().info("Vespa version to compile against is '" + compileVersion.toFullString() + "'.");
        getLog().info("Writing compile version to '" + output + "'.");
        Files.createDirectories(output.getParent());
        Files.writeString(output, compileVersion.toFullString());
    }

    /** Returns the major version declared in given deploymentXml, if any */
    static OptionalInt majorVersion(Path deploymentXml) {
        try {
            String xml = Files.readString(deploymentXml);
            Element deploymentTag = XML.getDocument(xml).getDocumentElement();
            if (deploymentTag == null) return OptionalInt.empty();
            String allowMajor = deploymentTag.getAttribute("major-version");
            if (allowMajor.isEmpty()) return OptionalInt.empty();
            return OptionalInt.of(parseMajor(allowMajor));
        } catch (NoSuchFileException ignored) {
            return OptionalInt.empty();
        } catch (IOException e) {
            throw new UncheckedIOException(e);
        }
    }

    private static int parseMajor(String s) {
        try {
            int major = Integer.parseInt(s);
            if (major < 1) throw new IllegalArgumentException("Major version must be positive, got " + major);
            return major;
        } catch (NumberFormatException e) {
            throw new IllegalArgumentException("Invalid major version '" + s + "'", e);
        }
    }

}

@@ -188,49 +188,59 @@
 hoo.
-component.Vtag;%0Aimport com.yahoo.text.XML
+text.XML;%0Aimport org.apache.maven.artifact.Artifact
 ;%0Aim
@@ -342,16 +342,62 @@
 ameter;%0A
+import org.apache.maven.project.MavenProject;%0A
 import o
@@ -1429,24 +1429,25 @@
 ajor));%0A
+%0A
         
 if (comp
@@ -1442,270 +1442,592 @@
     
-if (compileVersion.isAfter(Vtag.currentVersion))%0A            throw new IllegalStateException(%22
+MavenProject current = project;%0A        while (current.getParent() != null && current.getParent().getParentArtifact() != null)%0A            current = current.getParent();%0A%0A        Version 
 parent
- v
+V
 ersion
- (%22 + Vtag.currentVersion.toFullString() + %22) should be at least as %22 +%0A                                            %22high as the Vespa version to 
+;%0A        Artifact parentArtifact = current.getParentArtifact();%0A        if (parentArtifact != null && parentArtifact.getGroupId().matches(%22(com%5C%5C.yahoo%5C%5C.vespa%7Cai%5C%5C.vespa)(%5C%5C..+)?%22)) %7B%0A            parentVersion = Version.fromString(parentArtifact.getVersion());%0A            if (parentVersion.compareTo(compileVersion) %3C 0)%0A                throw new IllegalArgumentException(%22
 compile 
 agai
@@ -2022,23 +2022,23 @@
 compile 
-against
+version
  (%22 + co
@@ -2053,31 +2053,87 @@
 sion
-.toFullString() + %22)%22);
+ + %22) cannot be higher than parent version (%22 + parentVersion + %22)%22);%0A        %7D
 %0A%0A  

Read parent version from project, rather than using Vtag