package com.airlock.iam.plugin.config.manipulator;

import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.framework.misc.config.PluginConfigurationDictionary;
import com.airlock.iam.plugin.framework.misc.util.PluginConfigurationDictionaryUtils;
import com.airlock.iam.system.config.ConfigFormat;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.nio.file.Path;
import java.util.Optional;

@SuppressFBWarnings({"DM_EXIT", "REC_CATCH_EXCEPTION"})
public final class PluginConnecterMain {
   private static final String ALL_ENVIRONMENTS_IDENTIFIER = "[ALL]";
   private static final String COMMON_ENVIRONMENT_IDENTIFIER = "[SHARED]";

   private PluginConnecterMain() {
   }

   public static void main(String... args) {
      if (args.length != 11) {
         System.err
            .println(
               "expected arguments: connectMode, configFile, [outputFile], sourcePlugin, destinationPlugin, destinationProperty, [environment], [context], [listInsertionMode], [listInsertionArgument], [mapKey]"
            );
         System.exit(1);
      } else {
         String connectMode = args[0];
         Path configFile = Path.of(args[1]);
         Optional<Path> outputFile = args[2].isBlank() ? Optional.empty() : Optional.of(Path.of(args[2]));
         String sourcePlugin = args[3];
         String destinationPlugin = args[4];
         String destinationProperty = args[5];
         ConfigurationEnvironment environment = evaluateConfigurationEnvironment(args[6]);
         ConfigurationContext context = args[7].isBlank() ? ConfigurationContext.defaultContext() : ConfigurationContext.configurationContext(args[7]);
         String listInsertionMode = args[8];
         String listInsertionArgument = args[9];
         String mapKey = args[10];

         try {
            ConfigManipulationService service = new ConfigManipulationService(configFile);
            ConnectInfo connectInfo = new ConnectInfo(sourcePlugin, destinationPlugin, destinationProperty, environment, context);

            PluginConfigurationDictionary result = switch (connectMode) {
               case "plugin" -> service.connect(connectInfo);
               case "to-map" -> service.connectToMap(connectInfo, mapKey);
               case "to-list" -> {
                  switch (listInsertionMode) {
                     case "APPEND":
                        yield service.appendToList(connectInfo);
                     case "INDEX":
                        yield service.insertAtIndex(connectInfo, Integer.parseInt(listInsertionArgument));
                     case "INSERT_BEFORE":
                        yield service.insertBefore(connectInfo, listInsertionArgument);
                     case "INSERT_AFTER":
                        yield service.insertAfter(connectInfo, listInsertionArgument);
                     default:
                        throw new IllegalArgumentException("Connect to-list mode not implemented: " + listInsertionMode);
                  }
               }
               default -> throw new IllegalArgumentException("Connect mode not implemented: " + connectMode);
            };
            PluginConfigurationDictionaryUtils.atomicWriteDictionaryToFile(result, ConfigFormat.YAML_FORMAT, outputFile.orElse(configFile));
            System.out.println("Successfully connected the specified plugins");
         } catch (Exception e) {
            System.err.println("Error: " + e.getMessage());
            System.exit(1);
         }
      }
   }

   private static ConfigurationEnvironment evaluateConfigurationEnvironment(String environment) {
      return switch (environment) {
         case "[ALL]" -> throw new IllegalStateException("[ALL] environment identifier not implemented");
         case "[SHARED]" -> ConfigurationEnvironment.common();
         default -> environment.isBlank() ? ConfigurationEnvironment.common() : ConfigurationEnvironment.configurationEnvironment(environment);
      };
   }
}
