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

import static java.util.Arrays.asList;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.lowerCase;
import static org.apache.commons.lang3.StringUtils.trimToEmpty;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import de.ivu.elect.business.anschrift.entity.AnschriftArt;
import de.ivu.elect.business.person.entity.Geschlecht;
import de.ivu.elect.business.person.entity.Sperrmerkmal;
import de.ivu.elect.business.person.entity.Wahlrechtsausschluss;

import java.util.List;

// Cf. https://support.elect-it.com/ticket/secure/attachment/302005/2018-07-31_OSCI-XMeld_241_Spezifikation_final.pdf!
public interface XMeldPersonendaten {

  Logger LOG = LoggerFactory.getLogger(XMeldPersonendaten.class);

  static void warn(String msg) {
    LOG.warn(msg);
  }

  static List<Geschlecht> getGeschlechterSupported() {
    return asList(Geschlecht.MAENNLICH, Geschlecht.WEIBLICH, Geschlecht.DIVERS, Geschlecht.UNBEKANNT);
  }

  /**
   * @see https://www.xrepository.de/details/urn:de:dsmeld:schluesseltabelle:geschlecht
   */
  static Geschlecht internGeschlecht(String code) {
    String codeNormalized = lowerCase(trimToEmpty(code));

    switch (codeNormalized) {
      case "w" :
        return Geschlecht.WEIBLICH;
      case "m" :
        return Geschlecht.MAENNLICH;
      case "d" :
        return Geschlecht.DIVERS;
      case "x" :
        return Geschlecht.UNBEKANNT;

      default :
        break;
    }

    if (isNotBlank(codeNormalized)) {
      warn("Geschlecht übermittelt, aber nicht gemappt! [code = " + code + ", codeNormalized = " + codeNormalized + "]");
    }

    return Geschlecht.UNBEKANNT;
  }

  static String externGeschlecht(Geschlecht geschlecht) {
    if (geschlecht != null) {
      if (geschlecht.isWeiblich()) {
        return "w";
      }

      if (geschlecht.isMaennlich()) {
        return "m";
      }

      if (geschlecht.isDivers()) {
        return "d";
      }

      if (geschlecht.isUnbekannt()) {
        return "x";
      }
    }

    return "";
  }

  static PersonenregisterEinwohnerstatus internPersonenregisterEinwohnerstatus(boolean einwohnerstatusVerstorben) {
    if (Boolean.TRUE.equals(einwohnerstatusVerstorben)) {
      return PersonenregisterEinwohnerstatus.VERSTORBEN;
    }

    return PersonenregisterEinwohnerstatus.AKTIV;
  }

  static Sperrmerkmal internSperrmerkmal(String code) {
    String codeNormalized = lowerCase(trimToEmpty(code));

    if (isNotBlank(codeNormalized)) {
      warn("Sperrmerkmal übermittelt, aber nicht gemappt! [code = " + code + ", codeNormalized = " + codeNormalized + "]");
    }

    return Sperrmerkmal.UNBEKANNT;
  }

  /**
   * @see https://www.xrepository.de/details/urn:de:dsmeld:schluesseltabelle:wahlausschluss
   */
  static Wahlrechtsausschluss internWahlrechtsausschluss(String code) {
    String codeNormalized = lowerCase(trimToEmpty(code));

    switch (codeNormalized) {
      case "1" : // Ausschluss vom Wahlrecht
        return Wahlrechtsausschluss.AUSSCHLUSS_VOM_AKTIVEN_WAHLRECHT;
      case "2" : // Ausschluss von der Wählbarkeit
        return Wahlrechtsausschluss.AUSSCHLUSS_VOM_PASSIVEN_WAHLRECHT;

      default :
        break;
    }

    if (isNotBlank(codeNormalized)) {
      warn("Wahlrechtsausschluss übermittelt, aber nicht gemappt! [code = " + code + ", codeNormalized = " + codeNormalized + "]");
    }

    return Wahlrechtsausschluss.KEIN_AUSSCHLUSS;
  }

  static String externWahlrechtsausschluss(Wahlrechtsausschluss wahlrechtsausschluss) {
    if (wahlrechtsausschluss != null) {
      switch (wahlrechtsausschluss) {
        case AUSSCHLUSS_VOM_AKTIVEN_WAHLRECHT :
          return "1";
        case AUSSCHLUSS_VOM_PASSIVEN_WAHLRECHT :
          return "2";

        default :
          break;
      }
    }

    return "";
  }

  /**
   * @see https://www.xrepository.de/details/urn:de:dsmeld:schluesseltabelle:wohnungsstatus
   */
  static AnschriftArt internAnschriftArt(String code) {
    String codeNormalized = lowerCase(trimToEmpty(code));

    switch (codeNormalized) {
      case "0" : // Alleinige Wohnung
      case "1" : // Hauptwohnung
        return AnschriftArt.HAUPTWOHNUNG;
      case "2" : // Nebenwohnung
        return AnschriftArt.NEBENWOHNUNG;

      default :
        break;
    }

    if (isNotBlank(codeNormalized)) {
      warn("AnschriftArt übermittelt, aber nicht gemappt! [code = " + code + ", codeNormalized = " + codeNormalized + "]");
    }

    return AnschriftArt.UNBEKANNT;
  }

  static String externAnschriftArt(AnschriftArt anschriftArt) {
    if (anschriftArt != null) {
      switch (anschriftArt) {
        case HAUPTWOHNUNG :
          return "1";
        case NEBENWOHNUNG :
          return "2";

        default :
          break;
      }
    }

    return "";
  }
}
