
package de.ivu.elect.presentation.stimmeingabe;

import static java.util.stream.Collectors.joining;
import static org.apache.commons.lang3.StringUtils.equalsAnyIgnoreCase;

import java.util.HashSet;
import java.util.Optional;
import java.util.Set;

import javax.annotation.Nullable;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabe;
import de.ivu.elect.business.stimmeingabe.entity.StimmeingabeStimmen;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabefehler;
import de.ivu.elect.business.stimmeingabe.entity.Stimmeingabefehlerart;
import de.ivu.elect.jee.faces.Messages;

public class StimmeingabePlausiFehler {

  public static final String MESSAGE_KEY_FEHLER_AUF_UNTERSEITE_EINZAHL = "stimmeingabe.gruppe.stimmen.erfassen.fehler.auf.unterseite";

  public static final String MESSAGE_KEY_FEHLER_AUF_UNTERSEITE_MEHRZAHL = "stimmeingabe.gruppe.stimmen.erfassen.fehler.auf.unterseiten";

  public static final String STYLE_CLASS_ERROR = StimmeingabeStimmen.STYLE_CLASS_ERROR;

  public static final String STYLE_CLASS_WARNING = StimmeingabeStimmen.STYLE_CLASS_WARNING;

  public static final String STYLE_CLASS_HIGHLIGHT = "ui-state-important";

  private final Messages messages;

  private final Optional<Stimmeingabe> stimmeingabe;

  private final String stimmeingabeBezugId;

  private final String stimmeingabeBezug;

  private final Optional<Stimmeingabefehler> stimmeingabefehler;

  private final Stimmeingabefehlerart stimmeingabefehlerart;

  private final String beschreibung;

  private final Set<String> rowStyleClasses;

  public StimmeingabePlausiFehler(Messages messages, String stimmeingabeBezugId, String stimmeingabeBezug, Stimmeingabefehler stimmeingabefehler) {
    this(messages, stimmeingabefehler.getStimmeingabe(), stimmeingabeBezugId, stimmeingabeBezug, stimmeingabefehler, stimmeingabefehler.getFehlerart(), stimmeingabefehler.getBeschreibung());
  }

  public StimmeingabePlausiFehler(Messages messages, String stimmeingabeBezugId, String stimmeingabeBezug, Stimmeingabefehlerart stimmeingabefehlerart, String beschreibung) {
    this(messages, null, stimmeingabeBezugId, stimmeingabeBezug, stimmeingabefehlerart, beschreibung);
  }

  public StimmeingabePlausiFehler(Messages messages, Stimmeingabe stimmeingabe, String stimmeingabeBezugId, String stimmeingabeBezug, Stimmeingabefehlerart stimmeingabefehlerart, String beschreibung) {
    this(messages, stimmeingabe, stimmeingabeBezugId, stimmeingabeBezug, null, stimmeingabefehlerart, beschreibung);
  }

  private StimmeingabePlausiFehler(Messages messages, @Nullable Stimmeingabe stimmeingabe, String stimmeingabeBezugId, String stimmeingabeBezug, @Nullable Stimmeingabefehler stimmeingabefehler,
      Stimmeingabefehlerart stimmeingabefehlerart, String beschreibung) {
    super();

    this.messages = messages;

    this.stimmeingabe = Optional.ofNullable(stimmeingabe);
    this.stimmeingabeBezugId = stimmeingabeBezugId;
    this.stimmeingabeBezug = stimmeingabeBezug;

    this.stimmeingabefehler = Optional.ofNullable(stimmeingabefehler);
    this.stimmeingabefehlerart = stimmeingabefehlerart;

    this.beschreibung = beschreibung;

    this.rowStyleClasses = new HashSet<>();
  }

  public String getStimmeingabeBezugId() {
    return stimmeingabeBezugId;
  }

  public String getStimmeingabeBezug() {
    return stimmeingabeBezug;
  }

  public boolean hasStimmeingabeAnzahl() {
    return getStimmeingabe().map(Stimmeingabe::hasAnzahlGroesserGleichNull).orElse(false);
  }

  public Long getStimmeingabeAnzahl() {
    return getStimmeingabe().map(Stimmeingabe::getAnzahl).orElse(0L);
  }

  public boolean hasStimmeingabeAnzahlEingabe() {
    return getStimmeingabe().map(Stimmeingabe::hasAnzahlEingabe).orElse(false);
  }

  public String getStimmeingabeAnzahlEingabe() {
    return getStimmeingabe().map(Stimmeingabe::getAnzahlEingabe).orElse("");
  }

  public String getBeschreibung() {
    return beschreibung;
  }

  public boolean isHinweisFehlerAufUnterseite() {
    return equalsAnyIgnoreCase(beschreibung, messages.getMessageForMessageKey(MESSAGE_KEY_FEHLER_AUF_UNTERSEITE_EINZAHL), messages.getMessageForMessageKey(MESSAGE_KEY_FEHLER_AUF_UNTERSEITE_MEHRZAHL));
  }

  public boolean isMussFehler() {
    return getFehlerart().isError();
  }

  public boolean isKannFehler() {
    return getFehlerart().isWarning();
  }

  public Stimmeingabefehlerart getFehlerart() {
    return stimmeingabefehlerart;
  }

  public String getFehlerartName() {
    return messages.lokalisiere(getFehlerart());
  }

  public boolean hasStimmeingabe() {
    return getStimmeingabe().isPresent();
  }

  public Optional<Stimmeingabe> getStimmeingabe() {
    return stimmeingabe;
  }

  public Optional<Stimmeingabefehler> getStimmeingabefehler() {
    return stimmeingabefehler;
  }

  public String getRowStyleClass() {
    String result = "";

    if (isMussFehler()) {
      result += " " + STYLE_CLASS_ERROR + " ";
    } else if (isKannFehler()) {
      result += " " + STYLE_CLASS_WARNING + " ";
    }

    return result + " " + rowStyleClasses.stream().filter(StringUtils::isNotBlank).collect(joining(" ")) + " ";
  }

  public void addRowStyleClass(String styleClass) {
    rowStyleClasses.add(styleClass);
  }
}
