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

import static java.util.Objects.requireNonNull;
import static org.apache.commons.lang3.StringUtils.isNotBlank;
import static org.apache.commons.lang3.StringUtils.replace;

import java.io.Serializable;
import java.util.Locale;

import javax.inject.Inject;

import de.ivu.elect.business.ergebnis.entity.Ergebnisart;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.Wahlart;
import de.ivu.elect.business.wahl.entity.WahlartErgebnisart;
import de.ivu.elect.jee.faces.Messages;
import de.ivu.elect.jee.faces.UserLocale;

public class StimmeLabelMessages implements Serializable {

  private static final long serialVersionUID = 1L;

  private static final String MSG_KEY_INFIX_VORLAEUFIG = Ergebnisart.VORLAEUFIG.name();

  private static final String MSG_KEY_INFIX_ENDGUELTIG = Ergebnisart.ENDGUELTIG.name();

  @Inject
  private transient UserLocale userLocale;

  @Inject
  private transient Messages messages;

  public StimmeLabelMessages() {
    super();
  }

  public StimmeLabelMessages(UserLocale userLocale, Messages messages) {
    super();

    this.userLocale = userLocale;

    this.messages = messages;
  }

  public Locale getLocale() {
    return userLocale.getLocale();
  }

  public String getSingularOrDefault(Gebiet gebiet, WahlartErgebnisart ergebnisart, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKeyErgebnisart = getMessageKeyOrBlank(gebiet, ergebnisart, msgKeyInfix, "singular");

    if (isNotBlank(msgKeyErgebnisart)) {
      return getMessage(msgKeyErgebnisart, params);
    }

    return getSingularOrDefault(gebiet, msgKeyInfix, defaultValue, params);
  }

  public String getSingularOrDefault(Gebiet gebiet, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKey = getMessageKeyOrBlank(gebiet, msgKeyInfix, "singular");

    if (isNotBlank(msgKey)) {
      return getMessage(msgKey, params);
    }

    return defaultValue;
  }

  public String getPluralOrDefault(Gebiet gebiet, WahlartErgebnisart ergebnisart, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKeyErgebnisart = getMessageKeyOrBlank(gebiet, ergebnisart, msgKeyInfix, "plural");

    if (isNotBlank(msgKeyErgebnisart)) {
      return getMessage(msgKeyErgebnisart, params);
    }

    return getPluralOrDefault(gebiet, msgKeyInfix, defaultValue, params);
  }

  public String getPluralOrDefault(Gebiet gebiet, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKey = getMessageKeyOrBlank(gebiet, msgKeyInfix, "plural");

    if (isNotBlank(msgKey)) {
      return getMessage(msgKey, params);
    }

    return defaultValue;
  }

  public String getBezeichnungOrDefault(Gebiet gebiet, WahlartErgebnisart ergebnisart, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKeyErgebnisart = getMessageKeyOrBlank(gebiet, ergebnisart, msgKeyInfix, "bezeichnung");

    if (isNotBlank(msgKeyErgebnisart)) {
      return getMessageUnescaped(msgKeyErgebnisart, params);
    }

    return getBezeichnungOrDefault(gebiet, msgKeyInfix, defaultValue, params);
  }

  public String getBezeichnungOrDefault(Gebiet gebiet, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKey = getMessageKeyOrBlank(gebiet, msgKeyInfix, "bezeichnung");

    if (isNotBlank(msgKey)) {
      return getMessageUnescaped(msgKey, params);
    }

    return defaultValue;
  }

  public String getKennungFortlaufendOrDefault(Gebiet gebiet, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKey = getMessageKeyOrBlank(gebiet, msgKeyInfix, "kennung.fortlaufend");

    if (isNotBlank(msgKey)) {
      return getMessageUnescaped(msgKey, params);
    }

    return defaultValue;
  }

  public String getKennungOrDefault(Gebiet gebiet, WahlartErgebnisart ergebnisart, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKeyErgebnisart = getMessageKeyOrBlank(gebiet, ergebnisart, msgKeyInfix, "kennung");

    if (isNotBlank(msgKeyErgebnisart)) {
      return getMessageUnescaped(msgKeyErgebnisart, params);
    }

    return getKennungOrDefault(gebiet, msgKeyInfix, defaultValue, params);
  }

  public String getKennungOrDefault(Gebiet gebiet, String msgKeyInfix, String defaultValue, Object... params) {
    String msgKey = getMessageKeyOrBlank(gebiet, msgKeyInfix, "kennung");

    if (isNotBlank(msgKey)) {
      return getMessageUnescaped(msgKey, params);
    }

    return defaultValue;
  }

  public String getMessageKeyOrBlank(Gebiet gebiet, WahlartErgebnisart ergebnisart, String msgKeyInfix, String msgKeySuffix) {
    requireNonNullWahlart(gebiet);

    String msgKeyInfixErgebnisart = msgKeyInfix;

    if (ergebnisart.isVorlaeufig()) {
      msgKeyInfixErgebnisart = msgKeyInfixErgebnisart + "." + MSG_KEY_INFIX_VORLAEUFIG;
    }

    if (ergebnisart.isEndgueltig()) {
      msgKeyInfixErgebnisart = msgKeyInfixErgebnisart + "." + MSG_KEY_INFIX_ENDGUELTIG;
    }

    return getMessageKeyOrBlank(gebiet, msgKeyInfixErgebnisart, msgKeySuffix);
  }

  public String getMessageKeyOrBlank(Gebiet gebiet, String msgKeyInfix, String msgKeySuffix) {
    requireNonNullWahlart(gebiet);

    Wahl wahl = gebiet.getWahl();

    if (wahl != null) {
      String msgKeyInfixWahlebeneNormalized = normalizeWahlebene(gebiet);
      String msgKeyInfixWahlartNameNormalized = normalizeWahlartName(wahl.getWahlart());

      String msgKey = msgKeyInfixWahlartNameNormalized + "." + msgKeyInfixWahlebeneNormalized + "." + msgKeyInfix + "." + msgKeySuffix;

      if (existsMsgKey(msgKey)) {
        return msgKey;
      }

      msgKey = "DEFAULT." + msgKeyInfixWahlebeneNormalized + "." + msgKeyInfix + "." + msgKeySuffix;

      if (existsMsgKey(msgKey)) {
        return msgKey;
      }

      msgKey = msgKeyInfixWahlartNameNormalized + "." + msgKeyInfix + "." + msgKeySuffix;

      if (existsMsgKey(msgKey)) {
        return msgKey;
      }

      msgKey = "DEFAULT." + msgKeyInfix + "." + msgKeySuffix;

      if (existsMsgKey(msgKey)) {
        return msgKey;
      }
    }

    return null;
  }

  public String normalizeWahlebene(Gebiet gebiet) {
    return "<UNUSED>";
  }

  public String normalizeWahlebene(Wahlart wahlart) {
    return "<UNUSED>";
  }

  public String normalizeWahlartName(Wahlart wahlart) {
    return wahlart.getWahlartNameNormalized();
  }

  public boolean existsMsgKey(String msgKey) {
    return getMessages().isMessageKeyVorhanden(msgKey);
  }

  private String getMessageUnescaped(String msgKey, Object... params) {
    String result = getMessage(msgKey, params);

    String resultUnescaped = result;
    resultUnescaped = replace(resultUnescaped, "'{", "{");
    resultUnescaped = replace(resultUnescaped, "'}", "}");

    return resultUnescaped;
  }

  public String getMessage(String msgKey, Object... params) {
    return getMessages().getMessageForMessageKey(msgKey, params);
  }

  public String getMessage(Enum< ? > enumValue, Object... params) {
    return getMessages().lokalisiere(enumValue, params);
  }

  public Messages getMessages() {
    return messages;
  }

  private void requireNonNullWahlart(Gebiet gebiet) {
    requireNonNull(gebiet, "Gebiet darf nicht null sein");
    requireNonNull(gebiet.getWahl(), "Wahl darf nicht null sein");
    requireNonNull(gebiet.getWahl().getWahlart(), "Wahlart darf nicht null sein");
  }
}
