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

import com.airlock.iam.elog.api.ELogger;
import com.airlock.iam.elog.api.ELoggerFactory;
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.api.exception.ConfigurationException;
import com.airlock.iam.plugin.configeditor.data.tree.PluginConfigurationTreeItem;
import com.airlock.iam.plugin.configeditor.data.tree.TreeItem;
import com.airlock.iam.plugin.configeditor.util.GuiResources;
import com.airlock.iam.plugin.configeditor.util.VaadinHelper;
import com.airlock.iam.plugin.framework.application.configuration.MutablePluginConfiguration;
import com.airlock.iam.system.property.IamSystemProperties;
import com.google.common.annotations.VisibleForTesting;
import com.vaadin.v7.data.Item;
import java.nio.file.Path;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;

public class InheritanceTree extends ConfigurationTree {
   private static final ELogger LOG = ELoggerFactory.getLogger(InheritanceTree.class);

   public InheritanceTree(String displayName) {
      this(displayName, IamSystemProperties.getRootDirectory());
   }

   @VisibleForTesting
   InheritanceTree(String displayName, Path rootDirectory) {
      super(displayName, rootDirectory, false);
      this.getContainerDataSource().setItemSorter(new TreeItemSorter());
   }

   @Override
   protected void addPluginConfigurationItem(
      TreeItem<?> parentItemId,
      MutablePluginConfiguration pc,
      String caption,
      ConfigurationEnvironment env,
      ConfigurationContext context,
      Map<PluginConfiguration, List<ConfigurationException>> validations
   ) {
      if (pc != null) {
         boolean showDisplayName = parentItemId == null;
         PluginConfigurationTreeItem newItemId = new PluginConfigurationTreeItem(pc, caption, showDisplayName);
         Item pcItem = this.addItem(newItemId);
         if (parentItemId != null) {
            this.setParent(newItemId, parentItemId);
         }

         Set<ConfigurationException> localExceptions = new HashSet<>(validations.getOrDefault(pc, Collections.emptyList()));
         if (!localExceptions.isEmpty()) {
            VaadinHelper.setPropertyValue(pcItem, "icon", GuiResources.ICON_VALIDATION_ERROR);
         }

         newItemId.setErrors(localExceptions);

         for (MutablePluginConfiguration pcChild : this.getPluginConfigDict().getChildren(pc)) {
            this.addPluginConfigurationItem(newItemId, pcChild, pcChild.getPluginDisplayName(), env, null, validations);
         }
      }
   }

   @Override
   protected void updateTreeImpl() {
      long time = System.currentTimeMillis();

      for (MutablePluginConfiguration pc : this.getPluginConfigDict().getParentHierarchyRoots()) {
         this.addPluginConfigurationItem(
            null,
            pc,
            pc.getPluginDisplayName(),
            this.getApplication().getSelectedConfigurationEnvironment(),
            ConfigurationContext.defaultContext(),
            this.createValidationMap(this.getApplication().getGlobalErrors())
         );
      }

      LOG.debug("Updated InheritanceTree with " + this.size() + " nodes in " + (System.currentTimeMillis() - time) + " ms.");
   }
}
