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

import static org.apache.commons.lang3.StringUtils.isBlank;

import java.io.File;
import java.util.Date;

import javax.annotation.Nullable;
import javax.persistence.NoResultException;

import de.ivu.elect.business.konfiguration.boundary.AbstractKonfigurationDAO;
import de.ivu.elect.business.mandant.entity.EntityMitMandant;
import de.ivu.elect.business.mandant.entity.Mandant;
import de.ivu.elect.jee.exception.ElectCommonException;

public abstract class AbstractKonfigurationLoader extends AbstractCustomParameterLoader<ElectSystemMandantKonfigurationWerte, Konfiguration, KonfigurationLoaderContext> {

  private static final long serialVersionUID = 1L;

  protected AbstractKonfigurationLoader() {
    super();
  }

  public void setValue(ElectKonfigurationWerte template, String wert) {
    setValue(createSystemMandantContext(template), wert);
  }

  @Nullable
  public String resolveRequiredStringValue(ElectKonfigurationWerte template) {
    return getValueRequired(createSystemMandantContext(template));
  }

  @Nullable
  public String resolveStringValue(ElectKonfigurationWerte template) {
    return resolveStringValue(createSystemMandantContext(template));
  }

  @Nullable
  public Date resolveDateValue(ElectKonfigurationWerte template) {
    return resolveDateValue(createSystemMandantContext(template));
  }

  /**
   * @deprecated
   * @see {@link AbstractKonfigurationLoader#resolveLongValue(ElectKonfigurationWerte, long)}
   */
  @Deprecated
  @Nullable
  public Long resolveLongValueOptional(ElectKonfigurationWerte template) {
    String value = resolveStringValue(createSystemMandantContext(template));

    if (isBlank(value)) {
      return null;
    }

    return Long.parseLong(value);
  }

  public long resolveLongValue(ElectKonfigurationWerte template) {
    return resolveLongValue(createSystemMandantContext(template));
  }

  public long resolveLongValue(ElectKonfigurationWerte template, long defaultValue) {
    return resolveLongValue(createSystemMandantContext(template), defaultValue);
  }

  public int resolveIntegerValue(ElectKonfigurationWerte template) {
    return resolveIntegerValue(createSystemMandantContext(template));
  }

  public int resolveIntegerValue(ElectKonfigurationWerte template, int defaultValue) {
    return resolveIntegerValue(createSystemMandantContext(template), defaultValue);
  }

  public boolean resolveBooleanValue(ElectKonfigurationWerte template) {
    return resolveBooleanValue(createSystemMandantContext(template));
  }

  public File resolveFileValue(ElectKonfigurationWerte template) {
    return resolveFileValue(createSystemMandantContext(template));
  }

  public <V extends Enum< ? >> V resolveEnumValue(ElectKonfigurationWerte template, Class<V> enumClass) {
    return resolveEnumValue(createSystemMandantContext(template), enumClass);
  }

  public void setValue(Mandant mandant, MandantKonfigurationWerte template, String wert) {
    setValue(createCustomerMandantContext(mandant, template), wert);
  }

  @Nullable
  public String resolveRequiredStringValue(Mandant mandant, MandantKonfigurationWerte template) {
    return getValueRequired(createCustomerMandantContext(mandant, template));
  }

  @Nullable
  public String resolveStringValue(Mandant mandant, MandantKonfigurationWerte template) {
    return resolveStringValue(createCustomerMandantContext(mandant, template));
  }

  @Nullable
  public Date resolveDateValue(Mandant mandant, MandantKonfigurationWerte template) {
    return resolveDateValue(createCustomerMandantContext(mandant, template));
  }

  /**
   * @deprecated
   * @see {@link AbstractKonfigurationLoader#resolveLongValue(Mandant, MandantKonfigurationWerte, long)}
   */
  @Deprecated
  @Nullable
  public Long resolveLongValueOptional(Mandant mandant, MandantKonfigurationWerte template) {
    String value = resolveStringValue(createCustomerMandantContext(mandant, template));

    if (isBlank(value)) {
      return null;
    }

    return Long.parseLong(value);
  }

  public long resolveLongValue(Mandant mandant, MandantKonfigurationWerte template) {
    return resolveLongValue(createCustomerMandantContext(mandant, template));
  }

  public long resolveLongValue(Mandant mandant, MandantKonfigurationWerte template, long defaultValue) {
    return resolveLongValue(createCustomerMandantContext(mandant, template), defaultValue);
  }

  public int resolveIntegerValue(Mandant mandant, MandantKonfigurationWerte template) {
    return resolveIntegerValue(createCustomerMandantContext(mandant, template));
  }

  public int resolveIntegerValue(Mandant mandant, MandantKonfigurationWerte template, int defaultValue) {
    return resolveIntegerValue(createCustomerMandantContext(mandant, template), defaultValue);
  }

  public boolean resolveBooleanValue(Mandant mandant, MandantKonfigurationWerte template) {
    return resolveBooleanValue(createCustomerMandantContext(mandant, template));
  }

  public File resolveFileValue(Mandant mandant, MandantKonfigurationWerte template) {
    return resolveFileValue(createCustomerMandantContext(mandant, template));
  }

  public <V extends Enum< ? >> V resolveEnumValue(EntityMitMandant mandant, MandantKonfigurationWerte template, Class<V> enumClass) {
    return resolveEnumValue(createCustomerMandantContext(mandant, template), enumClass);
  }

  private KonfigurationLoaderContext createSystemMandantContext(ElectKonfigurationWerte template) {
    return new KonfigurationLoaderContext(null, template);
  }

  private KonfigurationLoaderContext createCustomerMandantContext(EntityMitMandant mandant, MandantKonfigurationWerte template) {
    return new KonfigurationLoaderContext(mandant.getMandant(), template);
  }

  private KonfigurationLoaderContext createCustomerMandantContext(Mandant mandant, MandantKonfigurationWerte template) {
    return new KonfigurationLoaderContext(mandant, template);
  }

  @Override
  protected void handleParameterNichtNichtGesetz(Object template) {
    throw new ElectCommonException(KonfigurationNichtGesetzException.MESSAGE_KEY, template);
  }

  @Override
  @Nullable
  protected Konfiguration getParameter(KonfigurationLoaderContext context) {
    return getParameter(context.getMandant(), context.getTemplate());
  }

  protected Konfiguration getParameter(Mandant mandant, ElectSystemMandantKonfigurationWerte template) {
    if (template instanceof ElectKonfigurationWerte) {
      return getParameter((ElectKonfigurationWerte) template);
    }

    if (template instanceof MandantKonfigurationWerte) {
      return getParameter(mandant, (MandantKonfigurationWerte) template);
    }

    throw new IllegalStateException("Unbekanntes Template: " + template);
  }

  @Nullable
  public Konfiguration getParameter(ElectKonfigurationWerte template) {
    try {
      return getKonfigurationDao().findBySystemSchluessel(template.getKey());
    } catch (NoResultException ignored) {
    }

    return null;
  }

  @Nullable
  public Konfiguration getParameter(Mandant mandant, MandantKonfigurationWerte template) {
    if (mandant != null) { // ELECT-11000, bspw. keine Session (mehr)...
      try {
        return getKonfigurationDao().findByMandantSchluessel(mandant, template.getKey());
      } catch (NoResultException ignored) {
      }
    }

    return null;
  }

  protected abstract AbstractKonfigurationDAO getKonfigurationDao();
}
