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.ConfigEditorApplication;
import com.airlock.iam.plugin.framework.misc.template.ConfigurationTemplate;
import com.airlock.iam.system.property.IamSystemProperties;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.shared.ui.ContentMode;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.Alignment;
import com.vaadin.ui.Button;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Window;
import com.vaadin.ui.Grid.ItemClick;
import com.vaadin.ui.Grid.SelectionMode;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import org.apache.commons.lang3.StringUtils;

public class LoadConfigTemplateDialog {
   private static final ELogger LOG = ELoggerFactory.getLogger(LoadConfigTemplateDialog.class);
   private final Window window;
   private final Grid<ConfigurationTemplate> templateTable;
   private final List<ConfigurationTemplate> templates = new ArrayList<>();
   private final Label templateNameLabel;
   private final Label templateDescriptionLabel;
   private final Label templateTagsLabel;
   private final Button loadTemplateButton;
   private ConfigurationTemplate selectedTemplate;

   @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", justification = "See ALIAM-15315")
   public LoadConfigTemplateDialog() {
      this.window = createWindow();
      this.templateTable = this.makeTemplateTable();
      this.templateNameLabel = new Label();
      this.templateNameLabel.setWidth(100.0F, Unit.PERCENTAGE);
      this.templateNameLabel.addStyleName("h2-bold");
      this.templateDescriptionLabel = new Label();
      this.templateDescriptionLabel.setWidth(100.0F, Unit.PERCENTAGE);
      this.templateDescriptionLabel.setContentMode(ContentMode.HTML);
      this.templateTagsLabel = new Label();
      this.templateNameLabel.setWidth(100.0F, Unit.PERCENTAGE);
      this.templateTagsLabel.setContentMode(ContentMode.HTML);
      this.loadTemplateButton = new Button("Use Selected Template");
      this.loadTemplateButton.setId("primaryButton");
      this.loadTemplateButton.setEnabled(false);
      this.loadTemplateButton.addStyleName("primary");
      this.loadTemplateButton.addClickListener(event -> this.loadTemplate(this.selectedTemplate));
      this.getWindow().setContent(this.buildLayout());
   }

   private void loadTemplate(ConfigurationTemplate template) {
      ConfigEditorApplication app = (ConfigEditorApplication)UI.getCurrent();

      try {
         File templateFileWithVariablesReplaced = template.getTemplateFileWithVariablesReplaced(IamSystemProperties.getInstanceName());
         app.loadConfigTemplate(templateFileWithVariablesReplaced);
      } catch (IOException e) {
         LOG.warn(LogTypes.CONFIGURATION_ERROR, "Cannot read configuration template or cannot replace variables in it: " + e.getMessage(), e);
      }

      this.getWindow().close();
   }

   public Window getWindow() {
      return this.window;
   }

   private static Window createWindow() {
      Window window = new Window("Select a configuration template");
      window.setWidth(800.0F, Unit.PIXELS);
      window.setResizable(false);
      window.setModal(true);
      return window;
   }

   private Grid<ConfigurationTemplate> makeTemplateTable() {
      Grid<ConfigurationTemplate> table = new Grid();
      table.setSelectionMode(SelectionMode.SINGLE);
      table.setHeightByRows(5.0);
      table.setWidth(100.0F, Unit.PERCENTAGE);
      table.addColumn(template -> (String)StringUtils.defaultIfBlank(template.getMetaData().getName(), "-")).setCaption("Name");
      table.addColumn(template -> (String)StringUtils.defaultIfBlank(this.tagsAsCommaSeparatedString(template), "")).setCaption("Tags");
      table.setItems(this.templates);
      table.addSelectionListener(event -> event.getFirstSelectedItem().ifPresentOrElse(this::templateSelected, this::clearSelectedTemplate));
      table.addItemClickListener(this::registerDoubleClickTemplateLoadListener);
      table.setStyleGenerator(item -> "with-hand");
      return table;
   }

   private void registerDoubleClickTemplateLoadListener(ItemClick<ConfigurationTemplate> event) {
      if (event.getMouseEventDetails().isDoubleClick()) {
         this.loadTemplate((ConfigurationTemplate)event.getItem());
      }
   }

   public void setTemplates(List<ConfigurationTemplate> templates) {
      this.templates.clear();
      this.templates.addAll(templates);
   }

   private VerticalLayout buildLayout() {
      VerticalLayout main = new VerticalLayout();
      main.setSpacing(false);
      main.addComponent(this.buildTablePanel());
      main.addComponent(this.makeDetailsPanel());
      return main;
   }

   private Panel buildTablePanel() {
      Panel panel = new Panel("Available Configuration Templates");
      panel.setContent(this.buildTopLayoutForTable());
      return panel;
   }

   private Panel makeDetailsPanel() {
      Panel detailsPanel = new Panel();
      detailsPanel.setCaption("Template Details");
      VerticalLayout contentToAdd = new VerticalLayout();
      contentToAdd.setSpacing(false);
      contentToAdd.addComponent(this.templateNameLabel);
      contentToAdd.addComponent(this.templateDescriptionLabel);
      contentToAdd.addComponent(this.templateTagsLabel);
      detailsPanel.setContent(contentToAdd);
      return detailsPanel;
   }

   private VerticalLayout buildTopLayoutForTable() {
      VerticalLayout top = new VerticalLayout();
      top.addComponent(this.templateTable);
      top.addComponent(this.loadTemplateButton);
      top.setComponentAlignment(this.loadTemplateButton, Alignment.MIDDLE_RIGHT);
      top.setMargin(new MarginInfo(true, false, true, false));
      return top;
   }

   private void templateSelected(ConfigurationTemplate selected) {
      this.templateNameLabel.setValue(selected.getMetaData().getName());
      this.templateDescriptionLabel.setValue(selected.getMetaData().getDescription());
      this.templateTagsLabel.setValue("<b>Tags:</b> " + this.tagsAsCommaSeparatedString(selected));
      this.selectedTemplate = selected;
      this.loadTemplateButton.setEnabled(true);
   }

   private void clearSelectedTemplate() {
      this.templateNameLabel.setValue(null);
      this.templateDescriptionLabel.setValue(null);
      this.templateTagsLabel.setValue(null);
      this.selectedTemplate = null;
      this.loadTemplateButton.setEnabled(false);
   }

   private String tagsAsCommaSeparatedString(ConfigurationTemplate selected) {
      return StringUtils.join(selected.getMetaData().getTags(), ", ");
   }
}
