
package de.ivu.elect.presentation.protokollierung.table;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.function.BiFunction;

import javax.inject.Inject;
import javax.inject.Named;

import de.ivu.elect.business.protokollierung.entity.ProtokollEintrag;
import de.ivu.elect.business.security.UseCasePermission;
import de.ivu.elect.business.security.control.ElectCommonPrincipal;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.presentation.dynamictable.AbstractColumnBuilder;
import de.ivu.elect.jee.presentation.dynamictable.ColumnEntry;
import de.ivu.elect.jee.presentation.dynamictable.ColumnType;
import de.ivu.elect.jee.security.AbstractPrincipal;

@Named(ProtokollEintragColumnBuilder.COMPONENT_NAME)
public class ProtokollEintragColumnBuilder extends AbstractColumnBuilder<ProtokollEintrag> {

  private static final long serialVersionUID = 1L;

  public static final String COMPONENT_NAME = "protokollEintragColumnBuilder";

  @Inject
  private transient ElectCommonPrincipal principal;

  @Inject
  private transient Messages messages;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragArtColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragZeitpunktColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragBenutzerkennungColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragAttributColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragAttributAlterWertColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragAttributNeuerWertColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragEntityLabelColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragEntityPkColumn;

  private AbstractProtokollEintragColumn<ProtokollEintrag> protokollEintragAttributTypColumn;

  public ProtokollEintragColumnBuilder() {
    super();
  }

  @Override
  protected void initColumns() {
    protokollEintragArtColumn = AbstractProtokollEintragColumn.createProtokollEintragProtokollEintragArtColumn(getMessages());
    protokollEintragZeitpunktColumn = AbstractProtokollEintragColumn.createProtokollEintragZeitpunktColumn(getMessages());
    if (principal.hasUseCasePermission(UseCasePermission.PROTOKOLL_EINTRAG_BENUTZERKENNUNG_SEHEN)) {
      protokollEintragBenutzerkennungColumn = AbstractProtokollEintragColumn.createProtokollEintragBenutzerkennungColumn(getMessages());
    } else {
      // ELECT-8253
      Map<String, Long> anwenderNameNummer = new ConcurrentHashMap<>();

      String system = messages.getMessageForMessageKey("protokoll.eintrag.verschleiert.benutzer.system");
      String anwender = messages.getMessageForMessageKey("protokoll.eintrag.verschleiert.benutzer.anwender");
      protokollEintragBenutzerkennungColumn = new AbstractProtokollEintragColumn<>("ProtokollEintrag-Benutzerkennung-verschleiert", messages,
        "protokoll.eintrag.verschleiert.header",
        ColumnType.STRING
        , p -> {
        if (AbstractPrincipal.SYSTEM_BENUTZERKENNUNG.equalsIgnoreCase(p.getBenutzerkennung())) {
          return system;
        } else {
          return anwender + " " + anwenderNameNummer.computeIfAbsent(p.getBenutzerkennung(), x -> anwenderNameNummer.size() + 1L);
        }
      });

    }

    protokollEintragAttributColumn = AbstractProtokollEintragColumn.createProtokollEintragAttributColumn(getMessages());
    protokollEintragAttributColumn.setDisplayFilter((protokollEintrag, value) -> {
      if (value == null) {
        return null;
      }

      return getMessage(value.toString());
    });

    BiFunction<ProtokollEintrag, Object, Object> wertDisplayFilter = (protokollEintrag, value) -> {
      if (value == null) {
        return null;
      }

      return protokollEintrag.getAttributTyp().getLocalized(value.toString(), getMessages(), getUserLocale().getLocale());
    };

    protokollEintragAttributTypColumn = AbstractProtokollEintragColumn.createProtokollEintragAttributTypColumn(getMessages());

    protokollEintragAttributAlterWertColumn = AbstractProtokollEintragColumn.createProtokollEintragAlterWertColumn(getMessages());
    protokollEintragAttributAlterWertColumn.setDisplayFilter(wertDisplayFilter);
    protokollEintragAttributNeuerWertColumn = AbstractProtokollEintragColumn.createProtokollEintragNeuerWertColumn(getMessages());
    protokollEintragAttributNeuerWertColumn.setDisplayFilter(wertDisplayFilter);

    protokollEintragEntityLabelColumn = new ProtokollEintragEntityLabelColumn(getMessages());
    protokollEintragEntityPkColumn = new ProtokollEintragEntityPkColumn(getMessages());
  }

  @Override
  protected List<ColumnEntry< ? super ProtokollEintrag>> getColumnEntriesSorted() {
    List<ColumnEntry< ? super ProtokollEintrag>> result = new ArrayList<>();

    result.add(protokollEintragZeitpunktColumn);
    result.add(protokollEintragBenutzerkennungColumn);
    result.add(protokollEintragArtColumn);

    result.add(protokollEintragEntityLabelColumn);
    result.add(protokollEintragEntityPkColumn);

    result.add(protokollEintragAttributColumn);
    result.add(protokollEintragAttributTypColumn);
    result.add(protokollEintragAttributAlterWertColumn);
    result.add(protokollEintragAttributNeuerWertColumn);

    return result;
  }

}
