package com.airlock.iam.plugin.configeditor.ui.components;

import com.airlock.iam.plugin.api.config.ConfigurationContext;
import com.airlock.iam.plugin.api.config.ConfigurationEnvironment;
import com.airlock.iam.plugin.api.config.PluginConfiguration;
import com.airlock.iam.plugin.configeditor.ConfigEditorApplication;
import com.airlock.iam.plugin.configeditor.data.PluginFieldsFormItem;
import com.airlock.iam.plugin.configeditor.ui.dialog.DeleteContextDialog;
import com.airlock.iam.plugin.configeditor.ui.dialog.NewContextDialog;
import com.airlock.iam.plugin.configeditor.ui.notifications.NotificationMessage;
import com.airlock.iam.plugin.configeditor.util.GuiResources;
import com.airlock.iam.plugin.framework.misc.config.PluginConfigurationPropertiesView;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.ui.Component;
import com.vaadin.ui.CssLayout;
import com.vaadin.ui.Notification;
import com.vaadin.ui.TabSheet;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Notification.Type;
import com.vaadin.ui.TabSheet.SelectedTabChangeEvent;
import com.vaadin.ui.TabSheet.SelectedTabChangeListener;
import com.vaadin.ui.TabSheet.Tab;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.HashMap;
import java.util.Map;
import java.util.Map.Entry;

public class PluginDetailTabsheet implements SelectedTabChangeListener {
   private static final int TAB_COUNT_DEFAULT = 3;
   private static final String TAB_CAPTION_PLUS = "+";
   private static final String TAB_CAPTION_MINUS = "-";
   private final TabSheet formTabSheet;
   private CssLayout plusTab;
   private CssLayout minusTab;
   private Tab previousSelectedTab;
   private ConfigurationContext selectedContext = ConfigurationContext.defaultContext();
   private Map<Tab, ConfigurationContext> mapTabContext;
   private boolean handleTabEvents;

   @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", justification = "See ALIAM-15315")
   public PluginDetailTabsheet() {
      this.formTabSheet = new TabSheet();
      this.formTabSheet.setWidth(100.0F, Unit.PERCENTAGE);
      this.formTabSheet.addSelectedTabChangeListener(this);
      this.formTabSheet.addStyleName("framed");
      this.formTabSheet.setTabsVisible(true);
   }

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

   public void selectedTabChange(SelectedTabChangeEvent event) {
      if (this.handleTabEvents) {
         Tab selectedTab = event.getTabSheet().getTab(event.getTabSheet().getSelectedTab());
         if (selectedTab.getCaption().equals("+")) {
            this.createNewContext();
         } else if (selectedTab.getCaption().equals("-")) {
            this.deleteContext();
         } else {
            this.setSelectedContext(this.mapTabContext.get(selectedTab));
            this.getConfigEditorApplication().updateFormFields();
         }

         if (!selectedTab.getCaption().equals("-") && !selectedTab.getCaption().equals("+")) {
            this.previousSelectedTab = selectedTab;
         }
      }
   }

   public PluginFieldsForm getActivePluginFieldsForm() {
      return this.formTabSheet.getSelectedTab() instanceof PluginFieldsForm ? (PluginFieldsForm)this.formTabSheet.getSelectedTab() : null;
   }

   public Component getTabsheet() {
      return this.formTabSheet;
   }

   public void clean() {
      this.mapTabContext = new HashMap<>();
      this.formTabSheet.removeAllComponents();
   }

   public void updateTabPositions() {
      this.plusTab = new CssLayout();
      this.plusTab.setCaption("+");
      this.formTabSheet.addTab(this.plusTab).setDescription("Add a new context.");
      this.minusTab = new CssLayout();
      this.minusTab.setCaption("-");
      this.formTabSheet.addTab(this.minusTab).setDescription("Remove an existing context.");
      if (this.formTabSheet.getComponentCount() == 3) {
         this.formTabSheet.getTab(this.minusTab).setEnabled(false);
      }
   }

   public void showHideFormTabSheet(boolean visible, VerticalLayout formContentLayout) {
      if (visible && this.isFormTabSheetAttached(formContentLayout)) {
         formContentLayout.addComponent(this.formTabSheet);
      } else if (!visible) {
         formContentLayout.removeComponent(this.formTabSheet);
      }
   }

   public void updateConfigurationContextTabCaptions(PluginConfiguration pConfig) {
      for (Entry<Tab, ConfigurationContext> e : this.mapTabContext.entrySet()) {
         ConfigurationContext context = e.getValue();
         if (!context.isDefaultContext() && this.hasContextSpecificValues(pConfig, context)) {
            e.getKey().setIcon(GuiResources.ICON_CONTEXT);
         } else {
            e.getKey().setIcon(null);
         }
      }
   }

   private boolean hasContextSpecificValues(PluginConfiguration pConfig, ConfigurationContext context) {
      ConfigurationEnvironment selectedEnvironment = this.getConfigEditorApplication().getSelectedConfigurationEnvironment();
      return new PluginConfigurationPropertiesView(pConfig, selectedEnvironment).inheritFromCommonEnvironment().getProperties().hasContext(context);
   }

   public Tab addTab(PluginFieldsForm pluginFieldsForm, String string) {
      return this.formTabSheet.addTab(pluginFieldsForm, string);
   }

   public void setSelectedTab(Tab tab) {
      this.formTabSheet.setSelectedTab(tab);
   }

   public void setSelectedTab(int selectedPosition) {
      this.setSelectedTab(this.formTabSheet.getTab(selectedPosition));
   }

   public int getSelectedTabPosition() {
      return this.formTabSheet.getTabPosition(this.formTabSheet.getTab(this.formTabSheet.getSelectedTab()));
   }

   public void setHandleTabEvents(boolean handleEvent) {
      this.handleTabEvents = handleEvent;
   }

   public void setContextTabCaptions(String selectedContextName, ConfigurationContext context, PluginFieldsForm pluginFieldsForm) {
      Tab tab = this.addTab(pluginFieldsForm, context.toString());
      PluginConfiguration selectedConfiguration = this.getConfigEditorApplication().getSelectedConfiguration();
      if (!context.isDefaultContext() && selectedConfiguration != null && this.hasContextSpecificValues(selectedConfiguration, context)) {
         tab.setIcon(GuiResources.ICON_CONTEXT);
      }

      this.mapTabContext.put(tab, context);
      if (selectedContextName.equals(context.toString())) {
         this.setSelectedTab(tab);
      }
   }

   public ConfigurationContext getSelectedContext() {
      return this.selectedContext;
   }

   public void setSelectedContext(ConfigurationContext selectedContext) {
      this.selectedContext = selectedContext;
   }

   public void setDefaultContext() {
      this.selectedContext = ConfigurationContext.defaultContext();
   }

   public void hideContextTabs(boolean hideTabs) {
      this.formTabSheet.setTabsVisible(!hideTabs);
   }

   private void deleteContext() {
      DeleteContextDialog dialog = new DeleteContextDialog();
      UI.getCurrent().addWindow(dialog);
      dialog.addCloseListener(e -> {
         DeleteContextDialog dialog1 = (DeleteContextDialog)e.getSource();
         ConfigurationContext contextToDelete = dialog1.getConfigurationContext();
         if (contextToDelete != null) {
            this.setDefaultContext();
            if (this.formTabSheet.getComponentCount() > 0) {
               this.formTabSheet.setSelectedTab(this.formTabSheet.getTab(0));
            }

            if (this.formTabSheet.getComponentCount() == 3) {
               this.formTabSheet.getTab(this.minusTab).setEnabled(false);
            }

            ConfigEditorApplication app = (ConfigEditorApplication)UI.getCurrent();
            app.getConfigurationDictionary().removeConfigurationContext(contextToDelete);
            app.updateValidationState();
            app.updateEnvironmentValuesState();
            app.updateFormFields();
            Notification.show(NotificationMessage.deleteContextMessage(contextToDelete.getIdentifier()), Type.TRAY_NOTIFICATION);
         } else if (this.previousSelectedTab == null) {
            this.formTabSheet.setSelectedTab(0);
         } else {
            this.formTabSheet.setSelectedTab(this.previousSelectedTab);
         }
      });
   }

   private void createNewContext() {
      this.handleTabEvents = false;
      NewContextDialog dialog = new NewContextDialog();
      UI.getCurrent().addWindow(dialog);
      dialog.addCloseListener(e -> {
         ConfigurationContext newContext = ((NewContextDialog)e.getSource()).getConfigurationContext();
         if (newContext != null) {
            ConfigEditorApplication app = (ConfigEditorApplication)UI.getCurrent();
            app.getConfigurationDictionary().addConfigurationContext(newContext);
            this.setSelectedContext(newContext);
            app.setHandleValidation(false);
            PluginFieldsForm pff = new PluginFieldsForm(true);
            pff.setItemDataSource(new PluginFieldsFormItem(app.getSelectedConfiguration(), app.getSelectedConfigurationEnvironment(), newContext));
            app.setHandleValidation(true);
            app.updateValidationState();
            Tab tab = this.formTabSheet.addTab(pff, newContext.toString());
            this.mapTabContext.put(tab, newContext);
            Tab newMinusTab = this.formTabSheet.getTab(this.minusTab);
            Tab newPlusTab = this.formTabSheet.getTab(this.plusTab);
            this.formTabSheet.setTabPosition(newMinusTab, this.formTabSheet.getTabPosition(newMinusTab) + 1);
            this.formTabSheet.setTabPosition(newPlusTab, this.formTabSheet.getTabPosition(newPlusTab) + 1);
            this.formTabSheet.setSelectedTab(tab);
            this.previousSelectedTab = tab;
            if (this.formTabSheet.getComponentCount() > 3) {
               this.formTabSheet.getTab(this.minusTab).setEnabled(true);
            }

            Notification.show(NotificationMessage.createContextMessage(newContext.getIdentifier()), Type.TRAY_NOTIFICATION);
         } else if (this.previousSelectedTab == null) {
            this.formTabSheet.setSelectedTab(0);
         } else {
            String tabIdentifier = this.previousSelectedTab.getCaption();

            for (int i = 0; i < this.formTabSheet.getComponentCount(); i++) {
               if (tabIdentifier.equals(this.formTabSheet.getTab(i).getCaption())) {
                  this.formTabSheet.setSelectedTab(this.formTabSheet.getTab(i));
               }
            }
         }

         this.handleTabEvents = true;
      });
   }

   private boolean isFormTabSheetAttached(VerticalLayout formContentLayout) {
      return formContentLayout.getComponentIndex(this.formTabSheet) == -1;
   }

   public void enableStyleForPropertyGroups(boolean groupsInitiated) {
      if (groupsInitiated) {
         this.formTabSheet.removeStyleName("no-groups");
      } else {
         this.formTabSheet.addStyleName("no-groups");
      }
   }
}
