
package de.ivu.elect.business.dokumente.entity;

import static org.apache.commons.lang3.StringUtils.endsWithIgnoreCase;
import static org.apache.commons.lang3.StringUtils.isNoneBlank;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

import java.util.function.BiPredicate;

import org.apache.commons.lang3.StringUtils;

import de.ivu.elect.business.datei.entity.Datei;
import de.ivu.elect.business.datei.entity.FileType;
import de.ivu.elect.business.mandant.entity.EntityMitMandant;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.util.CaseAndDiacriticIgnoringNormalizer;

public abstract class AbstractDokumentVorlage implements DokumentVorlageBase, EntityMitMandant {

  private static final long serialVersionUID = 1L;

  private static final CaseAndDiacriticIgnoringNormalizer STRING_NORMALIZER = CaseAndDiacriticIgnoringNormalizer.DEFAULT_INSTANCE;

  private static final BiPredicate<String, String> DEFAULT_STRING_NORMALIZED_MATCHER = StringUtils::containsIgnoreCase;

  protected AbstractDokumentVorlage() {
    super();
  }

  @Override
  public EntityMitMandant getParent() {
    Wahl wahl = getWahl();

    if (wahl != null) {
      return wahl;
    }

    return getWahltermin();
  }

  public boolean matchesName(String value) {
    return matchesName(value, DEFAULT_STRING_NORMALIZED_MATCHER);
  }

  public boolean matchesName(String value, BiPredicate<String, String> matcher) {
    return matchesNormalized(getName(), value, matcher);
  }

  public boolean matchesBeschreibung(String value) {
    return matchesBeschreibung(value, DEFAULT_STRING_NORMALIZED_MATCHER);
  }

  public boolean matchesBeschreibung(String value, BiPredicate<String, String> matcher) {
    return matchesNormalized(getBeschreibung(), value, matcher);
  }

  public boolean hasFileTypeDokumentVorlageArchive() {
    FileType fileType = getDatei().getFileType();

    return fileType != null && fileType.isDokumentVorlageArchive();
  }

  public boolean hasFileType(FileType fileType) {
    if (FileType.ODS.equals(fileType)) {
      // NOTE, dass der ursprüngliche Dateiname verwendet werden muss, da der hochgeladene Dateiname auf '.odt' endet!
      String originalDateiname = getDateinameOriginal();

      return endsWithIgnoreCase(originalDateiname, fileType.getFileExtension());
    }

    return fileType != null && fileType.equals(getDatei().getFileType());
  }

  public String getDateiname() {
    return getDatei().getDateiname();
  }

  public String getDateinameOriginal() {
    return getDatei().getOriginalDateiname();
  }

  public Datei getDatei() {
    return getDateiImport().getDatei();
  }

  protected void postSetWahl(Wahl alterWert, Wahl neuerWert) {
    // nichts zu tun
  }

  protected void preSetWahl(Wahl alterWert, Wahl neuerWert) {
    if (neuerWert == null) {
      setWahltermin(null);
    } else {
      setWahltermin(neuerWert.getWahltermin());
    }
  }

  private boolean matchesNormalized(String source, String value, BiPredicate<String, String> matcher) {
    return isNoneBlank(source, value) && matcher.test(normalize(source), normalize(value));
  }

  private String normalize(String value) {
    return STRING_NORMALIZER.getStringNormalized(trimToEmpty(value)).replaceAll("\\s+", "-");
  }
}
