package edu.kit.ipd.crowdcontrol.objectservice;

import edu.kit.ipd.crowdcontrol.objectservice.config.Config;
import edu.kit.ipd.crowdcontrol.objectservice.config.ConfigException;
import edu.kit.ipd.crowdcontrol.objectservice.config.ConfigPlatform;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.ho.yaml.Yaml;
import org.jooq.SQLDialect;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.Arrays;

/**
 * Loads the config from desired places and validates the completeness of the config
 *
 * @author Marcel Hollerbach
 */
public class ConfigLoader {
    private static final Logger LOGGER = LogManager.getLogger("Config");
    private final Config config;

    /**
     * Creates a new loader object
     * @throws FileNotFoundException For the case no config is found
     * @throws ConfigException For the case the config is not valid
     */
    public ConfigLoader() throws FileNotFoundException, ConfigException {
        InputStream configStream;
        if (System.getProperty("objectservice.config") != null) {
            LOGGER.debug("loading configuration from location: {}", System.getProperty("objectservice.config"));
            configStream = new FileInputStream(System.getProperty("objectservice.config"));
        } else {
            configStream = Main.class.getResourceAsStream("/config.yml");
        }

        config = Yaml.loadType(configStream, Config.class);
        if (System.getProperty("workerservice.url") != null) {
            config.deployment.workerService = System.getProperty("workerservice.url");
        }
        if (System.getProperty("origin.url") != null) {
            config.deployment.origin = System.getProperty("origin.url");
        }
        if (System.getProperty("workeruipublic.url") != null) {
            config.deployment.workerUIPublic = System.getProperty("workeruipublic.url");
        }
        if (System.getProperty("workeruilocal.url") != null) {
            config.deployment.workerUILocal = System.getProperty("workeruilocal.url");
        }

        config.platforms = Arrays.stream(config.platforms)
                .map(platform -> {
                    if (platform.name == null) {
                        if (platform.type.equals("dummy")) {
                            platform.name = "Dummy";
                        } else {
                            LOGGER.warn("Platform (type: {}) without a name will be ignored.", platform.type);
                        }
                    }

                    return platform;
                })
                .filter(platform -> platform.name != null && !Boolean.getBoolean(platform.name.toLowerCase() + ".disabled"))
                .toArray(ConfigPlatform[]::new);

        configValidate(config);
    }

    /**
     * check if a string is empty or null
     * @param val the value to check
     * @return true if the value is not null and not empty
     */
    private boolean NullOrEmpty(String val) {
        return !(val != null && !val.isEmpty());
    }

    /**
     * Validate the given config
     * @param config config to validate
     * @throws ConfigException thrown when there is a config exception
     */
    private void configValidate(Config config) throws ConfigException {
        if (config.database.maintainInterval < 0)
            throw new ConfigException("negative maintainInterval of database is not valid");
        if (NullOrEmpty(config.database.dialect) || SQLDialect.valueOf(config.database.dialect) == null)
            throw new ConfigException("Dialect does not exist");
        if ((config.database.writing == null ||
                config.database.readonly == null) &&
                NullOrEmpty(config.database.databasepool))
            throw new ConfigException("Database users have to be set!");
        if (NullOrEmpty(config.database.url))
            throw new ConfigException("Database url is not present!");
        if (NullOrEmpty(config.deployment.workerService))
            throw new ConfigException("WorkerService is not found");
        if (NullOrEmpty(config.deployment.workerUILocal) && config.deployment.workerUIPublic == null)
            throw new ConfigException("WorkerUi urls are not found!");
        if (NullOrEmpty(config.moneytransfer.notificationMailAddress))
            throw new ConfigException("Notification mail adress is empty");
    }

    public Config getConfig() {
        return config;
    }
}

@@ -2108,32 +2108,50 @@
 l%22);%0A        %7D%0A%0A
+        try %7B%0A    
         config.p
@@ -2209,16 +2209,20 @@
         
+    
 .map(pla
@@ -2232,16 +2232,20 @@
 rm -%3E %7B%0A
+    
         
@@ -2301,32 +2301,36 @@
                 
+    
 if (platform.typ
@@ -2346,24 +2346,28 @@
 %22dummy%22)) %7B%0A
+    
             
@@ -2423,32 +2423,36 @@
                 
+    
 %7D else %7B%0A       
@@ -2476,39 +2476,97 @@
     
+ 
-LOGGER.warn(%22Platform (type: %7B%7D
+   throw new RuntimeException(new ConfigException(%22Platform (type: %22 + platform.type + %22
 ) wi
@@ -2599,23 +2599,9 @@
 ed.%22
-, platform.type
+)
 );%0A 
@@ -2615,34 +2615,42 @@
                 
-%7D%0A
+    %7D%0A    
                 
@@ -2672,24 +2672,28 @@
             
+    
 return platf
@@ -2717,11 +2717,19 @@
     
-%7D)%0A
+    %7D)%0A    
     
@@ -2763,33 +2763,8 @@
 m -%3E
- platform.name != null &&
  !Bo
@@ -2840,16 +2840,20 @@
         
+    
 .toArray
@@ -2876,16 +2876,238 @@
 %5D::new);
+%0A        %7D catch (RuntimeException e) %7B%0A            if (e.getCause() instanceof ConfigException) %7B%0A                throw (ConfigException) e.getCause();%0A            %7D else %7B%0A                throw e;%0A            %7D%0A        %7D
 %0A%0A      

Throw error in case of platform without a name