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

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.configeditor.command.RemovePluginConfigurationCommand;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Component;
import com.vaadin.ui.HorizontalLayout;
import com.vaadin.ui.Label;
import com.vaadin.ui.Notification;
import com.vaadin.ui.Panel;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Button.ClickEvent;
import com.vaadin.ui.Notification.Type;
import com.vaadin.v7.ui.CheckBox;
import com.vaadin.v7.ui.OptionGroup;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;

public class DeletePluginConfigurationDialog extends Window {
   private static final ELogger LOG = ELoggerFactory.getLogger(DeletePluginConfigurationDialog.class);
   private final CheckBox deleteChildren;
   private final MutablePluginConfiguration toBeDeleted;
   private final OptionGroup deleteOptions;
   private static final String DETACH_PLUGIN_OPTION_MSG = "Detach all contained plugins (may leave unconnected plugins).";
   private static final String DELETE_PLUGIN_OPTION_MSG = "Delete all contained plugins, which are not contained in any other plugin, recursively. Other cross-references (e.g. step-ids) are not considered.";
   private static final String DELETE_CHILDREN_OPTION_MSG = "Delete all children.";
   private boolean deleted;

   @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", justification = "See ALIAM-15315")
   public DeletePluginConfigurationDialog(MutablePluginConfiguration pc) {
      this.toBeDeleted = pc;
      this.setProperties();
      VerticalLayout vl = this.createMainLayout(pc);
      Panel inheritancePanel = new Panel("Inheritance");
      inheritancePanel.setWidth(100.0F, Unit.PERCENTAGE);
      Panel compositionPanel = new Panel("Composition");
      compositionPanel.setWidth(100.0F, Unit.PERCENTAGE);
      compositionPanel.setHeight(110.0F, Unit.PIXELS);
      this.deleteChildren = new CheckBox("Delete all children.", false);
      this.deleteChildren.setId("deleteAllChildrenCheckbox");
      this.deleteOptions = this.makeDeleteOptionGroup();
      VerticalLayout deleteChildrenLayout = new VerticalLayout(new Component[]{this.deleteChildren});
      deleteChildrenLayout.setSpacing(false);
      inheritancePanel.setContent(deleteChildrenLayout);
      VerticalLayout deleteOptionsLayout = new VerticalLayout(new Component[]{this.deleteOptions});
      deleteOptionsLayout.setSpacing(false);
      compositionPanel.setContent(deleteOptionsLayout);
      compositionPanel.setId("compositionPanel");
      vl.addComponent(inheritancePanel);
      vl.addComponent(compositionPanel);
      HorizontalLayout hl = this.createButtonLayout();
      vl.addComponent(hl);
      ((Button)hl.getComponent(0)).focus();
      this.setContent(vl);
      UI.getCurrent().addWindow(this);
   }

   public DeletePluginConfigurationDialog(MutablePluginConfiguration pc, String htmlId) {
      this(pc);
      this.setId(htmlId);
   }

   public void cancelButtonClick(ClickEvent event) {
      UI.getCurrent().removeWindow(this);
   }

   public void deleteButtonClick(ClickEvent event) {
      try {
         new RemovePluginConfigurationCommand(
               this.toBeDeleted,
               (Boolean)this.deleteChildren.getValue(),
               this.deleteOptions
                  .getValue()
                  .equals(
                     "Delete all contained plugins, which are not contained in any other plugin, recursively. Other cross-references (e.g. step-ids) are not considered."
                  )
            )
            .execute();
         this.deleted = true;
         UI.getCurrent().removeWindow(this);
      } catch (IllegalStateException e) {
         LOG.error(LogTypes.SERVER_INFO_SYS, "IllegalStateException: " + e.getMessage(), e);
         Notification.show("Error occurred: " + e.getMessage(), Type.ERROR_MESSAGE);
      }
   }

   public boolean didIt() {
      return this.deleted;
   }

   @SuppressFBWarnings("POTENTIAL_XML_INJECTION")
   private Panel makePluginLabel(MutablePluginConfiguration pc) {
      Panel panel = new Panel("Delete Plugin Configuration");
      StringBuilder builder = new StringBuilder(100);
      builder.append("<span class=\"v-delete-plugin-highlight\">").append(pc.getPluginClassDisplayName());
      if (pc.getPluginDisplayName() != null && !pc.getPluginDisplayName().isEmpty()) {
         builder.append(" (").append(pc.getPluginDisplayName()).append(")");
      }

      builder.append("</span>");
      Label label = new Label(builder.toString());
      label.setWidth(100.0F, Unit.PERCENTAGE);
      label.setContentMode(ContentMode.HTML);
      VerticalLayout vl = new VerticalLayout(new Component[]{label});
      vl.setSpacing(false);
      panel.setContent(vl);
      return panel;
   }

   private void setProperties() {
      this.setCaption("Delete a plugin configuration");
      this.setModal(true);
      this.setResizable(false);
   }

   private VerticalLayout createMainLayout(MutablePluginConfiguration pc) {
      VerticalLayout vl = new VerticalLayout();
      vl.setHeightUndefined();
      vl.addComponent(this.makePluginLabel(pc));
      return vl;
   }

   private HorizontalLayout createButtonLayout() {
      HorizontalLayout hl = new HorizontalLayout();
      hl.setWidth(100.0F, Unit.PERCENTAGE);
      Button deleteButton = new Button("Delete");
      deleteButton.setId("primaryButton");
      deleteButton.addClickListener(this::deleteButtonClick);
      deleteButton.setClickShortcut(13, new int[0]);
      deleteButton.addStyleName("button-delete");
      Button cancelButton = new Button("Cancel");
      cancelButton.setId("cancelButton");
      cancelButton.addClickListener(this::cancelButtonClick);
      hl.addComponent(cancelButton);
      hl.addComponent(deleteButton);
      hl.setComponentAlignment(deleteButton, Alignment.MIDDLE_RIGHT);
      return hl;
   }

   private OptionGroup makeDeleteOptionGroup() {
      OptionGroup options = new OptionGroup();
      options.setImmediate(true);
      options.setBuffered(false);
      options.setNullSelectionAllowed(false);
      options.addItem("Detach all contained plugins (may leave unconnected plugins).");
      options.addItem(
         "Delete all contained plugins, which are not contained in any other plugin, recursively. Other cross-references (e.g. step-ids) are not considered."
      );
      options.select("Detach all contained plugins (may leave unconnected plugins).");
      options.addStyleName("linewrap");
      return options;
   }
}
