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

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
import com.airlock.iam.elog.api.LogTypes;
import com.airlock.iam.plugin.api.annotation.config.DeprecatedPlugin;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.exception.InitializeException;
import com.airlock.iam.plugin.configeditor.ConfigEditorApplication;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import com.airlock.iam.plugin.framework.misc.config.PluginConfigurationDictionary;
import com.vaadin.ui.UI;
import com.vaadin.v7.data.Property.ValueChangeEvent;
import com.vaadin.v7.shared.ui.combobox.FilteringMode;
import com.vaadin.v7.ui.ComboBox;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Optional;

public class PluginComboBox extends ComboBox {
   private static final ELogger LOG = ELoggerFactory.getLogger(PluginComboBox.class);
   private Optional<SelectablePluginConfigurations> selectablePluginConfs;

   @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", justification = "See ALIAM-15315")
   public PluginComboBox() {
      this.setFilteringMode(FilteringMode.CONTAINS);
      this.addValueChangeListener(this::handleValueChange);
      this.setPageLength(20);
   }

   public Class<?> getType() {
      return MutablePluginConfiguration.class;
   }

   public void initSelectablePluginsWithGlobalPluginReference(MutablePluginConfiguration target, Class<?> baseClass, ConfigurationEnvironment env) throws InitializeException {
      this.selectablePluginConfs = Optional.of(new SelectablePluginConfigurations(target, baseClass, this.getDictionary(), env));
      this.selectablePluginConfs.get().fillComboBoxWithGlobalPluginReference(this);
   }

   public void initSelectablePluginsWithDefaultPlugin(
      MutablePluginConfiguration target, Class<?> baseClass, Class<?> defaultValue, ConfigurationEnvironment env
   ) throws InitializeException {
      this.selectablePluginConfs = Optional.of(new SelectablePluginConfigurations(target, baseClass, this.getDictionary(), env));
      this.selectablePluginConfs.get().fillComboBoxWithDefaultPlugin(this, defaultValue);
   }

   public void initSelectablePlugins(MutablePluginConfiguration target, Class<?> baseClass, ConfigurationEnvironment env) throws InitializeException {
      this.selectablePluginConfs = Optional.of(new SelectablePluginConfigurations(target, baseClass, this.getDictionary(), env));
      this.selectablePluginConfs.get().fillComboBox(this);
   }

   public void initSelectablePlugins(SelectablePluginConfigurations selectablePluginConfigurations) {
      this.selectablePluginConfs = Optional.ofNullable(selectablePluginConfigurations);
      this.selectablePluginConfs.ifPresent(pc -> pc.fillComboBox(this));
   }

   private PluginConfigurationDictionary getDictionary() {
      return ((ConfigEditorApplication)UI.getCurrent()).getConfigurationDictionary();
   }

   private MutablePluginConfiguration getSelectedPluginConfig() {
      return (MutablePluginConfiguration)this.getValue();
   }

   private void handleValueChange(ValueChangeEvent event) {
      if (event.getProperty().getValue() != null) {
         this.setTextInputAllowed(false);

         try {
            if (this.isSelectedPluginDeprecated()) {
               this.addStyleName("deprecated");
            } else {
               this.removeStyleName("deprecated");
            }

            if (!this.isSelectedPluginLicensed()) {
               this.addStyleName("unlicensed");
            } else {
               this.removeStyleName("unlicensed");
            }
         } catch (InitializeException e) {
            LOG.error(LogTypes.CONFIGURATION_ERROR, "Could not load plugin class: " + e.getMessage(), e);
         }
      } else if (this.selectablePluginConfs.map(configurations -> !configurations.hasGlobalReference()).orElse(true)) {
         this.setTextInputAllowed(true);
      }
   }

   public void updateSelectablePluginConfigurations() {
      if (this.selectablePluginConfs.isPresent()) {
         this.selectablePluginConfs.get().fillComboBox(this);
      }
   }

   private boolean isSelectedPluginDeprecated() throws InitializeException {
      return this.getSelectedPluginConfig().getPluginClass().isAnnotationPresent(DeprecatedPlugin.class);
   }

   private boolean isSelectedPluginLicensed() {
      ConfigEditorApplication configEditor = (ConfigEditorApplication)UI.getCurrent();
      return configEditor.getLicenseManager().isPluginClassLicensed(this.getSelectedPluginConfig().getPluginClassName());
   }

   public void removePluginsWithoutDisplayName() {
      if (this.selectablePluginConfs.isPresent()) {
         this.selectablePluginConfs.get().removePluginsWithoutDisplayName(this);
      }
   }
}
