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

import com.airlock.iam.plugin.configeditor.ConfigEditorApplication;
import com.airlock.iam.plugin.configeditor.data.ConfigContainer;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import com.google.common.base.Predicates;
import com.google.common.collect.FluentIterable;
import com.vaadin.event.dd.acceptcriteria.ClientSideCriterion;
import com.vaadin.event.dd.acceptcriteria.SourceIs;
import com.vaadin.ui.AbstractOrderedLayout;
import com.vaadin.ui.Component;
import com.vaadin.ui.UI;
import com.vaadin.ui.VerticalLayout;
import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
import java.util.Optional;

public class PluginTreeUI extends VerticalLayout {
   private static final String MODULES_TREE_DEFAULT_CAPTION = "Modules";
   private static final String UNCONNECTED_TREE_DEFAULT_CAPTION = "Unconnected Plugins";
   private static final String INHERITANCE_TREE_DEFAULT_CAPTION = "Inheritance Tree";
   private final ConfigurationTreeToolbar treeSelectToolbar;
   private final PluginTreeUI.TreesLayout trees;

   @SuppressFBWarnings(value = "MC_OVERRIDABLE_METHOD_CALL_IN_CONSTRUCTOR", justification = "See ALIAM-15315")
   public PluginTreeUI() {
      this.setMargin(false);
      this.setHeightUndefined();
      this.trees = new PluginTreeUI.TreesLayout();
      this.treeSelectToolbar = new ConfigurationTreeToolbar(this.trees);
      this.treeSelectToolbar.selectTree(this.trees.modulesTree);
      AbstractOrderedLayout treesLayout = this.trees.getLayout();
      this.addComponents(new Component[]{this.treeSelectToolbar.getLayout(), treesLayout});
      this.setExpandRatio(treesLayout, 1.0F);
   }

   public void selectUnconnectedPluginsTree() {
      this.treeSelectToolbar.selectTree(this.trees.unconnectedPluginsTree);
   }

   public void selectModulesTree() {
      this.treeSelectToolbar.selectTree(this.trees.modulesTree);
   }

   public void setConfiguration(ConfigContainer configContainer) {
      for (ConfigurationTree tree : this.trees.allTrees()) {
         tree.setConfiguration(configContainer);
      }

      this.treeSelectToolbar.getLayout().setEnabled(true);
   }

   public void selectPluginConfiguration(MutablePluginConfiguration configuration) {
      this.trees.selectPluginConfiguration(configuration);
   }

   public void unselectPluginConfiguration() {
      this.trees.unselectPluginConfiguration();
   }

   public void updateTrees() {
      for (ConfigurationTree tree : this.trees.allTrees()) {
         tree.updateTree();
      }
   }

   public ClientSideCriterion getDnDAcceptCriterion() {
      return new SourceIs((Component[])this.trees.allTrees().toArray(ConfigurationTree.class));
   }

   private static final class TreesLayout implements TreeContainer {
      private final ConfigEditorApplication application;
      private final VerticalLayout layout = new VerticalLayout();
      private ConfigurationTree visibleTree;
      private final ModulesTree modulesTree;
      private final UnconnectedPluginsTree unconnectedPluginsTree;
      private final Optional<InheritanceTree> inheritanceTree;

      private TreesLayout() {
         this.application = (ConfigEditorApplication)UI.getCurrent();
         this.modulesTree = new ModulesTree("Modules");
         this.unconnectedPluginsTree = new UnconnectedPluginsTree("Unconnected Plugins");
         this.inheritanceTree = Optional.of(new InheritanceTree("Inheritance Tree"));
         this.inheritanceTree.get().addStyleName("pluginTrees");
         this.modulesTree.addStyleName("pluginTrees");
         this.unconnectedPluginsTree.addStyleName("pluginTrees");
         this.layout.setSpacing(false);
         this.layout.setMargin(false);
         this.layout.setSizeFull();

         for (Component tree : this.allTrees()) {
            this.layout.addComponent(tree);
            tree.setSizeFull();
            tree.setVisible(false);
         }
      }

      public AbstractOrderedLayout getLayout() {
         return this.layout;
      }

      public void selectPluginConfiguration(MutablePluginConfiguration configuration) {
         this.visibleTree.pluginSelection().selectPluginConfiguration(configuration, this.application.isPluginTreeLinkedWithEditor());
      }

      public void unselectPluginConfiguration() {
         this.visibleTree.pluginSelection().unselectPluginConfiguration();
      }

      public FluentIterable<ConfigurationTree> allTrees() {
         return FluentIterable.from(new ConfigurationTree[]{this.modulesTree, this.unconnectedPluginsTree, this.inheritanceTree.orElse(null)})
            .filter(Predicates.notNull());
      }

      @Override
      public void showTree(ConfigurationTree tree) {
         if (this.visibleTree != null) {
            this.visibleTree.setVisible(false);
         }

         tree.setVisible(true);
         this.visibleTree = tree;
         this.selectPluginConfiguration(this.application.getSelectedConfiguration());
      }

      @Override
      public ModulesTree getModulesTree() {
         return this.modulesTree;
      }

      @Override
      public Optional<InheritanceTree> getInheritanceTree() {
         return this.inheritanceTree;
      }

      @Override
      public UnconnectedPluginsTree getUnconnectedPluginsTree() {
         return this.unconnectedPluginsTree;
      }
   }
}
