package com.airlock.iam.plugin.configeditor.command;

import com.airlock.iam.plugin.configeditor.data.ConfigurableProperty;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import java.util.List;
import java.util.Map;
import java.util.Objects;

public final class ChangePropertyConfigurationCommand<T> implements ConfigEditorCommand {
   private final ConfigurableProperty property;
   private final T newValue;

   public static ChangePropertyConfigurationCommand.Builder<MutablePluginConfiguration> createChangePluginPropertyConfigurationCmdBuilder() {
      return new ChangePropertyConfigurationCommand.ChangePluginPropertyConfigurationCmdBuilder();
   }

   public static ChangePropertyConfigurationCommand.Builder<Map<String, MutablePluginConfiguration>> createChangePluginMapPropertyConfigurationCmdBuilder() {
      return new ChangePropertyConfigurationCommand.ChangePluginMapPropertyConfigurationCmdBuilder();
   }

   public static ChangePropertyConfigurationCommand.Builder<List<MutablePluginConfiguration>> createChangePluginListPropertyConfigurationCmdBuilder() {
      return new ChangePropertyConfigurationCommand.ChangePluginListPropertyConfigurationCmdBuilder();
   }

   private ChangePropertyConfigurationCommand(ChangePropertyConfigurationCommand.Builder<T> builder) {
      this.property = builder.property;
      this.newValue = builder.newValue;
   }

   @Override
   public final void execute() {
      Objects.requireNonNull(this.property, "property must not be null");
      this.property.setValue(this.newValue);
   }

   public abstract static class Builder<T> {
      private ConfigurableProperty property;
      private T newValue;

      public ChangePropertyConfigurationCommand.Builder<T> property(ConfigurableProperty aProperty) {
         Objects.requireNonNull(aProperty, "property must not be null");
         this.property = aProperty;
         return this;
      }

      public ChangePropertyConfigurationCommand.Builder<T> newValue(T aNewValue) {
         this.newValue = aNewValue;
         return this;
      }

      public abstract ChangePropertyConfigurationCommand<T> build();
   }

   private static class ChangePluginListPropertyConfigurationCmdBuilder extends ChangePropertyConfigurationCommand.Builder<List<MutablePluginConfiguration>> {
      @Override
      public ChangePropertyConfigurationCommand<List<MutablePluginConfiguration>> build() {
         return new ChangePropertyConfigurationCommand<>(this);
      }
   }

   private static class ChangePluginMapPropertyConfigurationCmdBuilder
      extends ChangePropertyConfigurationCommand.Builder<Map<String, MutablePluginConfiguration>> {
      @Override
      public ChangePropertyConfigurationCommand<Map<String, MutablePluginConfiguration>> build() {
         return new ChangePropertyConfigurationCommand<>(this);
      }
   }

   private static class ChangePluginPropertyConfigurationCmdBuilder extends ChangePropertyConfigurationCommand.Builder<MutablePluginConfiguration> {
      @Override
      public ChangePropertyConfigurationCommand<MutablePluginConfiguration> build() {
         return new ChangePropertyConfigurationCommand<>(this);
      }
   }
}
