package org.pdxfinder;

import org.pdxfinder.utils.DataProviders;
import org.pdxfinder.utils.DataProviders.DataProvider;
import org.pdxfinder.utils.DataProviders.DataProviderGroup;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
import picocli.CommandLine.Command;
import picocli.CommandLine.Option;
import picocli.CommandLine.ArgGroup;

import java.io.File;
import java.util.*;
import java.util.concurrent.Callable;

@Component
@Command(name = "indexer",
    mixinStandardHelpOptions = true,
    subcommands = {FinderCommandLine.Load.class})
@Order(value = -100)
public class FinderCommandLine implements Callable<Integer> {

    @Override
    public Integer call() {
        return 23;
    }

    @Component
    @Order(value = -100)
    @Command(name = "load",
        description = "Loads and transforms data into the PDXFinder.",
        mixinStandardHelpOptions = true,
        exitCodeOnExecutionException = 34)
    static class Load implements Callable<Integer> {

        Logger log = LoggerFactory.getLogger(Load.class);

        @Autowired
        private FinderLoader finderLoader;

        @Option(
            names = {"-d", "--data-dir"},
            required = true,
            description = "Path of the PDXFinder data directory " +
                "(default: [${DEFAULT-VALUE}], set in application.properties)")
        private File dataDirectory;

        @Option(names = {"-c", "--cache"},
                description = "Clear cached data and reload, including NCIT ontology terms, etc.")
        private boolean loadCacheRequested;

        @Option(names = {"-k", "--keep-db"},
                description = "Skips clearing of the database before loading new data.")
        private boolean keepDatabaseRequested;

        @Option(names = "--spring.config.location")
        private String springConfigLocation;

        @ArgGroup(multiplicity = "0..1")
        Exclusive datasetRequested;

        static class Exclusive {

            @Option(
                    names = {"-g", "--group"},
                    arity = "1",
                    description = "Load the data for groups of dataProvider (default: [${DEFAULT-VALUE}]). " +
                            "Accepted Values: [@|cyan ${COMPLETION-CANDIDATES} |@]")
            private DataProviderGroup dataProviderGroup = DataProviderGroup.All;

            @Option(
                    names = {"-o", "--only"}, arity = "1..*",
                    description = "Load only the data for the listed dataProvider. " +
                            "Accepted Values: [@|cyan ${COMPLETION-CANDIDATES} |@]")
            private DataProvider[] dataProvider;

            public DataProviderGroup getDataProviderGroup() {
                return dataProviderGroup;
            }

            public DataProvider[] getDataProvider() {
                return dataProvider;
            }
        }

        @Override
        public Integer call() {

            log.info("Loading using supplied parameters:\n{}", this);
            List<DataProvider> providersRequested = getListOfRequestedProviders();

            finderLoader.run(
                providersRequested,
                dataDirectory,
                loadCacheRequested,
                keepDatabaseRequested
            );
            return 0;
        }

        List<DataProvider> getListOfRequestedProviders() {

            if (datasetRequested.getDataProvider() != null) {
                return Arrays.asList(datasetRequested.getDataProvider());
            } else {
                return new ArrayList<>();
            }
        }

        @Override
        public String toString() {
            return new StringJoiner("\n", Load.class.getSimpleName() + "[\n", "\n]")
                .add("dataDirectory=" + dataDirectory)
                .add("clearCacheRequested=" + loadCacheRequested)
                .add("keepDatabaseRequested=" + keepDatabaseRequested)
                .add("springConfigLocation='" + springConfigLocation + "'")
                .add("datasetRequested=" + getListOfRequestedProviders())
                .toString();
        }
    }

}

@@ -3445,32 +3445,33 @@
 n 0;%0A        %7D%0A%0A
+%0A
         List%3CDat
@@ -3530,58 +3530,344 @@
     
-if (datasetRequested.getDataProvider() != null
+Optional%3CDataProvider%5B%5D%3E dataProviders = Optional.ofNullable(%0A                    datasetRequested.getDataProvider()%0A            );%0A%0A            Optional%3CDataProviderGroup%3E dataProviderGroup = Optional.ofNullable(%0A                    datasetRequested.getDataProviderGroup()%0A            );%0A%0A            if (dataProviders.isPresent()
 ) %7B%0A
+%0A
     
@@ -3903,33 +3903,146 @@
 ist(data
-setRequested.getD
+Providers.get());%0A            %7D else if (dataProviderGroup.isPresent()) %7B%0A%0A                return DataProviders.getProvidersFrom(d
 ataProvi
@@ -4044,16 +4044,25 @@
 Provider
+Group.get
 ());%0A   
@@ -4117,24 +4117,24 @@
 ayList%3C%3E();%0A
-
             
@@ -4127,32 +4127,33 @@
 ;%0A            %7D%0A
+%0A
         %7D%0A%0A     

Refactor getListOfRequestedProviders to avoid errors when no dataProvider or dataProviderGroup is supplied e.g during load All or caching