package com.airlock.iam.servicecontainer.app.infrastructure.webapp.view;

import com.airlock.iam.servicecontainer.app.application.configuration.TaskSchedule;
import com.airlock.iam.servicecontainer.app.infrastructure.webapp.presenter.TaskSchedulerServicePresenter;
import com.airlock.iam.servicecontainer.app.infrastructure.webapp.util.TranslatedKeyValueTable;
import com.vaadin.shared.ui.MarginInfo;
import com.vaadin.ui.VerticalLayout;
import java.util.HashMap;
import java.util.Map;

public class TaskSchedulerView extends GenericServiceView {
   private final TaskSchedulerServicePresenter taskSchedulerServicePresenter;
   private final Map<String, TaskRepresentation> taskRepresentations = new HashMap<>();
   private VerticalLayout allTasksLayout;
   private TranslatedKeyValueTable<String, Long> intervalMillisTable;

   public TaskSchedulerView(TaskSchedulerServicePresenter newTaskSchedulerServicePresenter) {
      super(newTaskSchedulerServicePresenter);
      this.taskSchedulerServicePresenter = newTaskSchedulerServicePresenter;
   }

   @Override
   public void init() {
      VerticalLayout layout = new VerticalLayout();
      layout.setSpacing(false);
      layout.setMargin(false);
      layout.addComponent(super.getLayout());
      VerticalLayout detailLayout = new VerticalLayout();
      detailLayout.setSpacing(false);
      detailLayout.setMargin(new MarginInfo(true, false, true, false));
      layout.addComponent(detailLayout);
      this.allTasksLayout = new VerticalLayout();
      this.allTasksLayout.setSpacing(false);
      this.allTasksLayout.setMargin(new MarginInfo(false, true, false, true));
      detailLayout.addComponent(this.allTasksLayout);
      this.intervalMillisTable = TranslatedKeyValueTable.buildTable();
      this.allTasksLayout.addComponent(this.intervalMillisTable);
      this.intervalMillisTable.setStyleName("sc-detailed-table");
      this.intervalMillisTable.addKeyValuePair("taskschedulerservice.check-interval-millis", this.taskSchedulerServicePresenter.getCheckIntervalMillis());

      for (TaskSchedule taskSchedule : this.taskSchedulerServicePresenter.getTaskSchedules()) {
         this.createNewTaskRepresentationAndAddToLayout(taskSchedule);
      }

      this.setCompositionRoot(layout);
   }

   private void createNewTaskRepresentationAndAddToLayout(TaskSchedule taskSchedule) {
      TaskRepresentation taskRepresentation = new TaskRepresentation(this.taskSchedulerServicePresenter, taskSchedule);
      this.taskRepresentations.put(taskSchedule.getTaskName(), taskRepresentation);
      this.allTasksLayout.addComponent(taskRepresentation.getLayout());
   }

   private void updateIntervalMillisTable() {
      this.intervalMillisTable.update("taskschedulerservice.check-interval-millis", Long.toString(this.taskSchedulerServicePresenter.getCheckIntervalMillis()));
   }

   @Override
   public void update(ServiceContainerUI serviceContainerUI) {
      super.update(serviceContainerUI);
      if (serviceContainerUI.isAttached()) {
         serviceContainerUI.access(
            () -> {
               this.updateIntervalMillisTable();

               for (TaskRepresentation taskRepresentation : this.taskRepresentations.values()) {
                  taskRepresentation.setShouldBeRemoved(true);
               }

               for (TaskSchedule taskSchedule : this.taskSchedulerServicePresenter.getTaskSchedules()) {
                  TaskRepresentation taskRepresentation = this.taskRepresentations.get(taskSchedule.getTaskName());
                  if (taskRepresentation != null) {
                     taskRepresentation.updateUI();
                     taskRepresentation.setShouldBeRemoved(false);
                  } else {
                     this.createNewTaskRepresentationAndAddToLayout(taskSchedule);
                  }
               }

               this.taskRepresentations
                  .values()
                  .stream()
                  .filter(TaskRepresentation::shouldBeRemoved)
                  .forEach(task -> this.allTasksLayout.removeComponent(task.getLayout()));
               this.taskRepresentations.entrySet().removeIf(e -> e.getValue().shouldBeRemoved());
            }
         );
      }
   }
}
