
package de.ivu.elect.business.ui.boundary;

import static java.util.Arrays.asList;
import static java.util.stream.Collectors.toList;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;

import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.business.ui.boundary.AbstractUITableColumnOrderDAO;
import de.ivu.elect.business.ui.boundary.UITableColumnOrderDAO;
import de.ivu.elect.business.ui.entity.UITableColumnOrder;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.presentation.dynamictable.ColumnBuilder;
import de.ivu.elect.jee.presentation.dynamictable.ColumnEntry;

public class UITableColumnOrderKonfiguration {

  private static final UITableColumnOrderComparator UI_TABLE_COLUMN_ORDER_COMPARATOR = new UITableColumnOrderComparator();

  public UITableColumnOrderKonfiguration() {
    super();
  }

  public boolean isColumnAnzuzeigen(Map<String, UITableColumnOrder> columnKnownPerColumnKey, ColumnEntry< ? > columnEntry) {
    return isColumnAnzuzeigen(columnKnownPerColumnKey, generateColumnKey(columnEntry));
  }

  public boolean isColumnAnzuzeigen(Map<String, UITableColumnOrder> columnKnownPerColumnKey, UITableColumnOrder uiTableColumnOrder) {
    return isColumnAnzuzeigen(columnKnownPerColumnKey, uiTableColumnOrder.getColumnKey());
  }

  private boolean isColumnAnzuzeigen(Map<String, UITableColumnOrder> columnPerColumnKey, String columnKey) {
    return isNotBlank(columnKey) && (!columnPerColumnKey.containsKey(columnKey) || Boolean.TRUE.equals(columnPerColumnKey.get(columnKey).getAnzeigen()));
  }

  public List<UITableColumnOrder> collectColumnsInColumnBuilderVerfuegbar(ColumnBuilder< ? > columnBuilder) {
    return collectColumnsInColumnBuilder(columnBuilder, columnBuilder.getAllColumns().stream().collect(toList()));
  }

  public List<UITableColumnOrder> collectColumnsInColumnBuilderAngezeigt(ColumnBuilder< ? > columnBuilder) {
    return collectColumnsInColumnBuilder(columnBuilder, columnBuilder.getColumns().stream().collect(toList()));
  }

  private List<UITableColumnOrder> collectColumnsInColumnBuilder(ColumnBuilder< ? > columnBuilder, List<ColumnEntry> columnEntries) {
    return collectColumnsInColumnBuilder(columnBuilder, columnEntries, UI_TABLE_COLUMN_ORDER_COMPARATOR);
  }

  private List<UITableColumnOrder> collectColumnsInColumnBuilder(ColumnBuilder< ? > columnBuilder, List<ColumnEntry> columnEntries, Comparator<UITableColumnOrder> comparator) {
    return columnEntries.stream() //
        .filter(Objects::nonNull) //
        .filter(ColumnEntry::isRendered) //
        .map(columnEntry -> {
          UITableColumnOrder uiTableColumnOrder = new UITableColumnOrder();
          uiTableColumnOrder.setColumnKey(generateColumnKey(columnEntry));
          uiTableColumnOrder.setColumnHeader(columnEntry.getHeader());

          return uiTableColumnOrder;
        }) //
        .sorted(comparator) //
        .collect(Collectors.toList());
  }

  public List<UITableColumnOrder> collectColumnsInDb(ElectCommonPrincipal principal, Wahl wahl, Wahltermin wahltermin, ColumnBuilder< ? > columnBuilder,
      AbstractUITableColumnOrderDAO uiTableColumnOrderDAO) {
    return collectColumnsInDb(principal, wahl, wahltermin, columnBuilder, uiTableColumnOrderDAO, UI_TABLE_COLUMN_ORDER_COMPARATOR);
  }

  public List<UITableColumnOrder> collectColumnsInDb(ElectCommonPrincipal principal, Wahl wahl, Wahltermin wahltermin, ColumnBuilder< ? > columnBuilder,
      AbstractUITableColumnOrderDAO uiTableColumnOrderDAO, Comparator<UITableColumnOrder> comparator) {
    return uiTableColumnOrderDAO.findByBenutzerKeyAndColumnBuilderKey(generateBenutzerKey(principal), generateColumnBuilderKey(wahl, wahltermin, columnBuilder)).stream() //
        .sorted(comparator) //
        .collect(toList());
  }

  public void persistColumnInDb(ElectCommonPrincipal principal, Wahl wahl, Wahltermin wahltermin, ColumnBuilder< ? > columnBuilder, UITableColumnOrder uiTableColumnOrder,
      UITableColumnOrderDAO uiTableColumnOrderDAO) {
    persistColumnsInDb(principal, wahl, wahltermin, columnBuilder, asList(uiTableColumnOrder), uiTableColumnOrderDAO);
  }

  public void persistColumnsInDb(ElectCommonPrincipal principal, Wahl wahl, Wahltermin wahltermin, ColumnBuilder< ? > columnBuilder, List<UITableColumnOrder> uiTableColumnOrders,
      UITableColumnOrderDAO uiTableColumnOrderDAO) {
    for (UITableColumnOrder uiTableColumnOrder : uiTableColumnOrders) {
      uiTableColumnOrder.setColumnBuilderKey(generateColumnBuilderKey(wahl, wahltermin, columnBuilder));
      uiTableColumnOrder.setBenutzerKey(generateBenutzerKey(principal));

      uiTableColumnOrderDAO.persist(uiTableColumnOrder);
    }
  }

  public void removeColumnsInDb(ElectCommonPrincipal principal, Wahl wahl, Wahltermin wahltermin, ColumnBuilder< ? > columnBuilder, UITableColumnOrderDAO uiTableColumnOrderDAO) {
    for (UITableColumnOrder uiTableColumnOrder : collectColumnsInDb(principal, wahl, wahltermin, columnBuilder, uiTableColumnOrderDAO)) {
      uiTableColumnOrderDAO.remove(uiTableColumnOrder);
    }
  }

  protected String generateBenutzerKey(ElectCommonPrincipal principal) {
    if (principal != null && principal.getLogin() != null) {
      return principal.getLogin().getBenutzerkennungMitMandant(); // ELECT-9182
    }

    return "";
  }

  protected String generateColumnBuilderKey(Wahl wahl, Wahltermin wahltermin, ColumnBuilder< ? > columnBuilder) {
    if (columnBuilder != null) {
      return columnBuilder.getName();
    }

    return "";
  }

  protected String generateColumnKey(ColumnEntry< ? > columnEntry) {
    if (columnEntry != null) {
      return columnEntry.getName();
    }

    return "";
  }
}
