package com.github.sormuras.bach.core;

import com.github.sormuras.bach.Bach;
import com.github.sormuras.bach.ToolCall;
import com.github.sormuras.bach.ToolOperator;
import java.io.PrintWriter;
import java.io.StringReader;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
import java.util.Properties;

public class Install implements ToolOperator {
  @Override
  public String name() {
    return "install";
  }

  @Override
  public int run(Bach bach, PrintWriter out, PrintWriter err, String... args) {
    for (var arg : args) {
      var path =
          arg.endsWith(".properties")
              ? Path.of(arg)
              : bach.configuration().paths().externalTools(arg + ".properties");
      generateLoadAndVerifyCalls(path).forEach(bach::run);
    }
    return 0;
  }

  List<ToolCall> generateLoadAndVerifyCalls(Path path) {
    var name = path.getFileName().toString();
    var tool = path.resolveSibling(name.substring(0, name.length() - 11));
    var properties = new Properties();
    try {
      properties.load(new StringReader(Files.readString(path)));
    } catch (Exception exception) {
      throw new RuntimeException("Reading entries failed: " + path);
    }
    var calls = new ArrayList<ToolCall>();
    for (var key : properties.stringPropertyNames()) {
      var source = properties.getProperty(key);
      var target = tool.resolve(key);
      calls.add(ToolCall.of("load-and-verify", target, source));
    }
    return List.copyOf(calls);
  }
}

@@ -159,16 +159,68 @@
 erator;%0A
+import com.github.sormuras.bach.internal.ArgVester;%0A
 import j
@@ -370,24 +370,51 @@
 .util.List;%0A
+import java.util.Optional;%0A
 import java.
@@ -484,360 +484,489 @@
 %7B%0A  
-@Override%0A  public String name() %7B%0A    return %22install%22;%0A  %7D%0A%0A  @Override%0A  public int run(Bach bach, PrintWriter out, PrintWriter err, String... args) %7B%0A    for (var arg : args) %7B%0A      var path =%0A          arg.endsWith(%22.properties%22)%0A              ? Path.of(arg)%0A              : bach.configuration().paths().externalTools(arg + %22.properties%22
+public record CLI(%0A      String tool, Optional%3CString%3E uri, Optional%3CString%3E user, Optional%3CString%3E repo) %7B%7D%0A%0A  @Override%0A  public int run(Bach bach, PrintWriter out, PrintWriter err, String... args) %7B%0A    var cli = ArgVester.create(CLI.class).parse(args);%0A    var target = bach.configuration().paths().externalTools(cli.tool() + %22.properties%22);%0A%0A    if (Files.notExists(target)) %7B%0A      var uri = cli.uri().orElse(computeUri(cli));%0A      bach.run(%22load%22, target, uri
 );%0A   
+ %7D%0A%0A
    
+ 
 gene
@@ -988,20 +988,22 @@
 fyCalls(
-path
+target
 ).forEac
@@ -1020,26 +1020,21 @@
 n);%0A
+%0A
     
-%7D%0A    
 return 0
 ;%0A  
@@ -1029,16 +1029,319 @@
 return 0
+;%0A  %7D%0A%0A  String computeUri(CLI cli) %7B%0A    return %22https://github.com/%22%0A        + cli.user().orElse(%22sormuras%22)%0A        + %22/%22%0A        + cli.repo().orElse(%22bach-external-tools%22)%0A        + %22/raw/main/properties/%22%0A        + cli.tool().split(%22@%22)%5B0%5D%0A        + %22/%22%0A        + cli.tool()%0A        + %22.properties%22
 ;%0A  %7D%0A%0A 

Improve `install` tool