package org.i2g.client;

import com.beust.jcommander.JCommander;
import com.beust.jcommander.Parameter;
import lombok.AccessLevel;
import lombok.NoArgsConstructor;
import lombok.NonNull;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.i2g.client.argument.converter.FileConverter;
import org.i2g.client.argument.converter.OutputTypeConverter;
import org.i2g.client.argument.validator.OutputDirectoryValidator;
import org.i2g.client.argument.validator.OutputTypeValidator;
import org.i2g.model.I2GContainer;
import org.i2g.service.FileReader;
import org.i2g.service.MetadataReader;
import org.i2g.service.writers.FileWriter;
import org.i2g.service.writers.OutputType;
import org.i2g.service.writers.WriterContext;
import org.springframework.boot.CommandLineRunner;

import java.io.File;
import java.util.List;
import java.util.Map;

@RequiredArgsConstructor
@NoArgsConstructor(access = AccessLevel.PRIVATE)
public class Images2GpxCommandLineRunner implements CommandLineRunner {

    @Parameter(names = {"-i", "--inputDirectory"},
            converter = FileConverter.class,
            description = "Directory containing your images", required = true)
    private File inputDirectory;

    @Parameter(names = {"-o", "--outputDirectory"},
            validateWith = OutputDirectoryValidator.class,
            converter = FileConverter.class,
            description = "Output Directory")
    private File outputDirectory = new File(System.getProperty("user.dir"));

    @Parameter(names = {"-t", "outputType"},
            validateWith = OutputTypeValidator.class,
            converter = OutputTypeConverter.class,
            description = "supported types [gpx, google-maps-markers, google-maps-polylines]")
    private OutputType outputType = OutputType.GPX;

    @Parameter(names = {"-r", "--recursive"},
            description = "Read the inputDirectory recursively")
    private boolean recursive = false;

    @Parameter(names = {"-k", "--apikey"},
            description = "Google Maps API Key. Only used for OutputType google-maps-polyline"
    )
    private String apiKey;

    @Parameter(names = {"?", "-h", "--help"}, help = true)
    boolean help = false;

    @NonNull
    private FileReader fileReaderService;

    @NonNull
    private MetadataReader metadataReaderService;

    @NonNull
    private Map<OutputType, FileWriter> writerRegistry;


    public void run(String[] args) {
        Images2GpxCommandLineRunner jcContext = new Images2GpxCommandLineRunner();
        JCommander jCommander = new JCommander(jcContext, args);
        ifHelpPrintAndExit(jcContext.help, jCommander);

        WriterContext wc = createWriterContext(jcContext);

        System.out.println(String.format("Processing all files in directory \"%s\"", wc.getInputDirectory()));
        System.out.println(String.format("Writing to %s", wc.getOutputDirectory()));

        List<File> allImageFiles = fileReaderService.readFiles(wc.getInputDirectory(), wc.getRecursive());
        List<I2GContainer> containers = metadataReaderService.getI2GContainers(allImageFiles);
        System.out.println(containers);

        // write coordinates to file
        FileWriter writer = writerRegistry.get(jcContext.outputType);
        writer.write(containers, wc);
    }

    private void ifHelpPrintAndExit(boolean help, JCommander jCommander) {
        if (help) {
            jCommander.usage();
            System.exit(0);
        }
    }

    private WriterContext createWriterContext(Images2GpxCommandLineRunner args) {
        if (args.outputType == OutputType.GM_POLYLINES && StringUtils.isEmpty(args.apiKey)) {
            System.out.println("for google-maps-polyline the attribute 'apikey' is required!");
            System.out.println("You can create a new API Key here: https://console.developers.google.com/apis/credentials");
        }

        return WriterContext.builder()
                .inputDirectory(args.inputDirectory)
                .outputDirectory(args.outputDirectory)
                .recursive(args.recursive)
                .apiKey(args.apiKey)
                .build();
    }
}

@@ -115,114 +115,9 @@
 bok.
-AccessLevel;%0Aimport lombok.NoArgsConstructor;%0Aimport lombok.NonNull;%0Aimport lombok.RequiredArgsConstructor
+*
 ;%0Aim
@@ -840,16 +840,24 @@
 RIVATE)%0A
+@Getter%0A
 public c
@@ -2094,16 +2094,24 @@
 ue)%0A    
+private 
 boolean 
@@ -2538,20 +2538,24 @@
 Context.
-h
+isH
 elp
+()
 , jComma
@@ -3481,25 +3481,28 @@
    if (args.
-o
+getO
 utputType ==
@@ -3498,16 +3498,18 @@
 tputType
+()
  == Outp
@@ -3556,22 +3556,27 @@
 ty(args.
-a
+getA
 piKey
+()
 )) %7B%0A   
@@ -3880,17 +3880,20 @@
 ry(args.
-i
+getI
 nputDire
@@ -3889,32 +3889,34 @@
 etInputDirectory
+()
 )%0A              
@@ -3939,17 +3939,20 @@
 ry(args.
-o
+getO
 utputDir
@@ -3957,16 +3957,18 @@
 irectory
+()
 )%0A      
@@ -3993,25 +3993,27 @@
 ve(args.
-r
+isR
 ecursive
 )%0A      
@@ -4004,16 +4004,18 @@
 ecursive
+()
 )%0A      
@@ -4037,22 +4037,27 @@
 ey(args.
-a
+getA
 piKey
+()
 )%0A      

clean up