package fi.evident.apina.gradle.tasks;

import fi.evident.apina.ApinaProcessor;
import fi.evident.apina.java.reader.Classpath;
import org.gradle.api.DefaultTask;
import org.gradle.api.file.FileCollection;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.InputFiles;
import org.gradle.api.tasks.OutputFile;
import org.gradle.api.tasks.TaskAction;
import org.intellij.lang.annotations.Language;

import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static java.util.Objects.requireNonNull;
import static org.gradle.util.GFileUtils.writeFile;

public class ApinaTask extends DefaultTask {

    private File target;

    private FileCollection classpath;

    private List<String> blackBoxClasses = new ArrayList<>();

    private Map<String,List<String>> imports = new HashMap<>();

    public static final String GENERATE_API_CLIENT_TASK_NAME = "apina";

    @TaskAction
    public void generateTypeScript() throws IOException {
        requireNonNull(classpath, "classpath not initialized");
        requireNonNull(target, "target not initialized");

        Classpath myClasspath = new Classpath();
        for (File file : classpath)
            myClasspath.addRoot(file.toPath());

        ApinaProcessor processor = new ApinaProcessor(myClasspath);

        for (@Language("RegExp") String pattern : blackBoxClasses)
            processor.settings.blackBoxClasses.addPattern(pattern);

        for (Map.Entry<String, List<String>> anImport : imports.entrySet())
            processor.settings.addImport(anImport.getKey(), anImport.getValue());

        String output = processor.process();

        writeFile(output, target, "UTF-8");
    }

    @InputFiles
    public FileCollection getClasspath() {
        return classpath;
    }

    public void setClasspath(FileCollection classpath) {
        this.classpath = classpath;
    }

    @OutputFile
    public File getTarget() {
        return target;
    }

    public void setTarget(File target) {
        this.target = target;
    }

    @Input
    public List<String> getBlackBoxClasses() {
        return blackBoxClasses;
    }

    public void setBlackBoxClasses(List<String> blackBoxTypePatterns) {
        this.blackBoxClasses = blackBoxTypePatterns;
    }

    @Input
    public Map<String, List<String>> getImports() {
        return imports;
    }

    public void setImports(Map<String, List<String>> imports) {
        this.imports = imports;
    }
}

@@ -120,16 +120,89 @@
 sspath;%0A
+import fi.evident.apina.spring.EndpointParameterNameNotDefinedException;%0A
 import o
@@ -1110,16 +1110,34 @@
 ption %7B%0A
+        try %7B%0A    
         
@@ -1192,32 +1192,36 @@
 ized%22);%0A        
+ 
+   
 requireNonNull(t
@@ -1263,16 +1263,20 @@
         
+    
 Classpat
@@ -1312,24 +1312,28 @@
 ();%0A        
+   
+ 
 for (File fi
@@ -1348,16 +1348,20 @@
 sspath)%0A
+    
         
@@ -1397,24 +1397,28 @@
 toPath());%0A%0A
+    
         Apin
@@ -1478,24 +1478,28 @@
 );%0A%0A        
+    
 for (@Langua
@@ -1549,32 +1549,36 @@
 es)%0A            
+    
 processor.settin
@@ -1622,24 +1622,28 @@
 );%0A%0A        
+  
+  
 for (Map.Ent
@@ -1698,16 +1698,20 @@
 ySet())%0A
+    
         
@@ -1793,16 +1793,20 @@
         
+   
+ 
 String o
@@ -1843,16 +1843,20 @@
         
+    
 writeFil
@@ -1879,24 +1879,265 @@
 , %22UTF-8%22);%0A
+        %7D catch (EndpointParameterNameNotDefinedException e) %7B%0A            getLogger().error(%22%7B%7D%5CnConsider adding 'compileJava %7B options.compilerArgs = %5B'-parameters'%5D %7D' to your build file.%22, e.getMessage());%0A            throw e;%0A        %7D%0A
     %7D%0A%0A    @

Add better error message for unresolved parameter names