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

import com.airlock.iam.plugin.configeditor.data.EnvironmentSpecificPropertyBean;
import com.airlock.iam.plugin.framework.misc.config.PropertyConfigurationWithPluginConfiguration;
import com.vaadin.event.selection.SelectionEvent;
import com.vaadin.server.Sizeable.Unit;
import com.vaadin.shared.data.sort.SortDirection;
import com.vaadin.ui.Component;
import com.vaadin.ui.Grid;
import com.vaadin.ui.Label;
import com.vaadin.ui.Panel;
import com.vaadin.ui.VerticalLayout;
import com.vaadin.ui.Grid.Column;
import com.vaadin.ui.Grid.SelectionMode;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Supplier;
import java.util.stream.Stream;

final class EnvironmentValuesPanel implements PanelContainer {
   private final Supplier<Stream<PropertyConfigurationWithPluginConfiguration>> dataSource;
   private final SelectionListener<EnvironmentSpecificPropertyBean> listener;
   private final Panel panel = new Panel();
   private final List<EnvironmentSpecificPropertyBean> properties = new ArrayList<>();
   private final Grid<EnvironmentSpecificPropertyBean> grid = new Grid();
   private final Label noEnvSpecificValuesMessage = new Label("There are no environment-specific properties defined.");

   public EnvironmentValuesPanel(
      Supplier<Stream<PropertyConfigurationWithPluginConfiguration>> dataSource, SelectionListener<EnvironmentSpecificPropertyBean> listener
   ) {
      this.dataSource = dataSource;
      this.listener = listener;
      this.configureGrid();
      this.panel.addStyleName("minimal");
      this.panel.setContent(this.buildLayout());
      this.panel.setId("envPropertiesPanel");
      this.panel.setSizeFull();
   }

   private VerticalLayout buildLayout() {
      VerticalLayout vl = new VerticalLayout();
      vl.addComponent(this.grid);
      this.noEnvSpecificValuesMessage.setWidth(100.0F, Unit.PERCENTAGE);
      vl.addComponent(this.noEnvSpecificValuesMessage);
      vl.setSizeFull();
      return vl;
   }

   private void configureGrid() {
      this.grid.setSelectionMode(SelectionMode.SINGLE);
      this.grid.setSizeFull();
      this.grid.setColumnReorderingAllowed(true);
      this.grid.setItems(this.properties);
      Column<EnvironmentSpecificPropertyBean, String> propertyName = this.grid
         .addColumn(EnvironmentSpecificPropertyBean::getPropertyName)
         .setCaption("Property");
      this.grid.addColumn(EnvironmentSpecificPropertyBean::getPluginNameAndId).setCaption("Plugin");
      this.grid.addColumn(EnvironmentSpecificPropertyBean::getContextName).setCaption("Context");
      this.grid.sort(propertyName, SortDirection.ASCENDING);
      this.grid.addSelectionListener(this::selectionChange);
      this.grid.setId("propertiesTable");
      this.grid.setVisible(false);
      this.grid.setStyleGenerator(item -> "with-hand");
   }

   @Override
   public void update() {
      this.properties.clear();
      this.dataSource.get().map(EnvironmentSpecificPropertyBean::new).forEach(this.properties::add);
      this.grid.getDataProvider().refreshAll();
      this.updateComponents();
   }

   private void updateComponents() {
      if (this.properties.isEmpty()) {
         this.noEnvSpecificValuesMessage.setVisible(true);
         this.grid.setVisible(false);
      } else {
         this.grid.setVisible(true);
         this.noEnvSpecificValuesMessage.setVisible(false);
      }
   }

   private void selectionChange(SelectionEvent<EnvironmentSpecificPropertyBean> event) {
      event.getFirstSelectedItem().ifPresent(this.listener::itemSelected);
   }

   @Override
   public Component getContent() {
      return this.panel;
   }
}
