
package de.ivu.elect.dokumente.konverter;

import javax.annotation.Nullable;
import javax.inject.Inject;

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

import de.ivu.elect.business.CurrentCustomer;
import de.ivu.elect.business.benutzerverwaltung.boundary.BenutzerDAO;
import de.ivu.elect.business.benutzerverwaltung.entity.Benutzer;
import de.ivu.elect.business.dokumente.control.DokumentExtraFileOutput;
import de.ivu.elect.business.dokumente.control.ElectDokumentContext;
import de.ivu.elect.business.gebietsbaum.boundary.GebietsartCreator;
import de.ivu.elect.business.konfiguration.entity.KonfigurationLoader;
import de.ivu.elect.business.wahl.boundary.WahlDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminDAO;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlParameterLoader;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.dokumente.BaseElectContext;
import de.ivu.elect.dokumente.BaseElectCustomDataDocumentBuilder;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;
import de.ivu.elect.presentation.person.PersonendatenFormatter;

public abstract class AbstractDokumentKonverter<C extends ElectDokumentContext> {

  @Inject
  private transient BenutzerDAO benutzerDAO;

  @Inject
  private transient WahlDAO wahlDAO;

  @Inject
  private transient WahlterminDAO wahlterminDAO;

  @Inject
  private transient PersonendatenFormatter personendatenFormatter;

  @Inject
  private transient GebietsartCreator gebietsartCreator;

  @Inject
  private transient BaseElectCustomDataDocumentBuilder baseElectCustomDataDocumentBuilder;

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  @Inject
  private transient WahlParameterLoader wahlParameterLoader;

  @Inject
  private transient KonfigurationLoader konfigurationLoader;

  @Inject
  private transient CurrentCustomer currentCustomer;

  private final Logger log;

  protected AbstractDokumentKonverter() {
    super();

    this.log = LoggerFactory.getLogger(getClass());
  }

  protected BaseElectContext createBaseElectContext(C context, DokumentExtraFileOutput dokumentExtraFileOutput) {
    return createBaseElectContext(context, dokumentExtraFileOutput, context.getWahltermin(), context.getWahl());
  }

  protected BaseElectContext createBaseElectContext(C context, DokumentExtraFileOutput dokumentExtraFileOutput, Wahl wahl) {
    if (wahl == null) {
      return createBaseElectContext(context, dokumentExtraFileOutput, null, null);
    }

    return createBaseElectContext(context, dokumentExtraFileOutput, wahl.getWahltermin(), wahl);
  }

  protected BaseElectContext createBaseElectContext(C context, DokumentExtraFileOutput dokumentExtraFileOutput, @Nullable Wahltermin wahltermin, @Nullable Wahl wahl) {
    BaseElectContext baseElectContext = new BaseElectContext(dokumentExtraFileOutput, attachIfPersistent(context.getBenutzer()), attach(wahltermin), attach(wahl), context.getMessages(),
        getPersonendatenFormatter(), gebietsartCreator.getGebietsartTemplates(context.getMandant()), baseElectCustomDataDocumentBuilder, gebietNummerFormatter, getWahlParameterLoader(),
        getKonfigurationLoader(), context.getMandant(), currentCustomer.getCustomer());
    baseElectContext.getContextParameters().putAll(context.getContextParameters()); // ELECT-10233

    return baseElectContext;
  }

  protected KonfigurationLoader getKonfigurationLoader() {
    return konfigurationLoader;
  }

  protected WahlParameterLoader getWahlParameterLoader() {
    return wahlParameterLoader;
  }

  protected PersonendatenFormatter getPersonendatenFormatter() {
    return personendatenFormatter;
  }

  protected Wahl attach(@Nullable Wahl wahl) {
    return wahlDAO.attach(wahl);
  }

  private Wahltermin attach(@Nullable Wahltermin wahltermin) {
    return wahlterminDAO.attach(wahltermin);
  }

  private Benutzer attachIfPersistent(Benutzer benutzer) {
    if (benutzer.isPersistent()) {
      return benutzerDAO.attach(benutzer);
    }

    return benutzer;
  }

  protected void info(String format, Object... params) {
    log.info(format, params);
  }

  protected void warn(String format, Throwable cause) {
    log.warn(format, cause);
  }

  protected void warn(String format, Object... params) {
    log.warn(format, params);
  }

  protected void error(String format, Object... params) {
    log.error(format, params);
  }

  protected void error(String format, Throwable cause) {
    log.error(format, cause);
  }
}
