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

import com.airlock.iam.configeditor.shared.domain.IamModuleConfigRoot;
import com.airlock.iam.plugin.configeditor.ConfigEditorApplication;
import com.airlock.iam.plugin.configeditor.data.PluginConfigurationFormItem;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import com.airlock.iam.plugin.framework.misc.config.PluginConfigurationDictionary;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.UI;
import com.vaadin.v7.data.Validator;
import com.vaadin.v7.data.Validator.InvalidValueException;
import com.vaadin.v7.ui.Field;
import com.vaadin.v7.ui.TextField;

public class PluginDisplayNameField {
   private final TextField field = new TextField();

   public PluginDisplayNameField(PluginConfigurationFormItem pcfItem, Object propertyId) {
      this.field.setCaption(null);
      this.field.setWidth(360.0F, Unit.PIXELS);
      this.field.setDescription("A human-readable identifier to describe plugins.");
      MutablePluginConfiguration pc = (MutablePluginConfiguration)pcfItem.getBean();
      if (IamModuleConfigRoot.isModuleTreeRoot(pc)) {
         pcfItem.getItemProperty(propertyId).setReadOnly(true);
      } else {
         this.field.addValidator(new PluginDisplayNameField.DisplayNameValidator(pc, this.getApplication().getConfigurationDictionary()));
      }

      this.field.setNullRepresentation("");
      this.field.setNullSettingAllowed(true);
      this.field.addValueChangeListener(event -> {
         if (!event.getProperty().isReadOnly()) {
            this.getApplication().updateTrees();
         }
      });
   }

   private ConfigEditorApplication getApplication() {
      return (ConfigEditorApplication)UI.getCurrent();
   }

   public Field<?> getField() {
      return this.field;
   }

   private record DisplayNameValidator(MutablePluginConfiguration pc, PluginConfigurationDictionary dict) implements Validator {
      public void validate(Object value) throws InvalidValueException {
         if (value == null) {
            if (!this.dict.getChildren(this.pc).isEmpty()) {
               throw new InvalidValueException("This configuration is a parent of another plugin. An display name is required.");
            }
         } else {
            if (value instanceof String stringValue) {
               String displayName = stringValue.trim();
               MutablePluginConfiguration existingWithSameId = this.dict.getByDisplayName(displayName);
               if (existingWithSameId != null && !this.pc.equals(existingWithSameId)) {
                  throw new InvalidValueException("The display name \"" + displayName + "\" is already in use.");
               }

               if (IamModuleConfigRoot.getByDisplayName(displayName) != null) {
                  throw new InvalidValueException("The display name \"" + displayName + "\" is reserved and may not be used.");
               }
            }
         }
      }
   }
}
