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

import de.ivu.elect.business.datei.entity.DateiImportBerichtCustomData;
import de.ivu.elect.business.email.control.EmailLayoutCreate;
import de.ivu.elect.business.email.control.EmailVorlageExchangeContext;
import de.ivu.elect.business.email.control.EmailVorlageImportExchange;
import de.ivu.elect.business.email.entity.EmailLayout;
import de.ivu.elect.business.email.entity.EmailVorlage;
import de.ivu.elect.business.email.entity.EmailVorlageMeta;
import de.ivu.elect.business.email.entity.EmailVorlageUK;
import de.ivu.elect.business.exchange.control.AbstractEntityImporter;
import de.ivu.elect.business.exchange.control.ImportExchange;
import de.ivu.elect.business.wahl.boundary.WahlDAO;
import de.ivu.elect.business.wahl.boundary.WahlterminDAO;
import de.ivu.elect.jee.entity.Meta;
import de.ivu.elect.jee.exchange.ImportOptions;
import de.ivu.elect.jee.exchange.Violations;

import javax.ejb.Stateless;
import javax.inject.Inject;
import javax.persistence.NoResultException;
import java.util.Collection;
import java.util.List;
import java.util.function.Function;

@Stateless
public class EmailVorlageImporter extends
    AbstractEntityImporter<EmailVorlage, EmailVorlageUK, EmailVorlageExchangeContext, DateiImportBerichtCustomData> {

  @Inject
  private transient EmailVorlageImportExchange emailVorlageImportExchange;

  @Inject
  private transient EmailVorlageMeta emailVorlageMeta;

  @Inject
  private transient EmailVorlageDAO emailVorlageDao;

  @Inject
  private transient EmailLayoutDAO emailLayoutDao;

  @Inject
  private transient EmailLayoutCreate emailLayoutCreate;

  @Inject
  private transient WahlterminDAO wahlterminDao;

  @Inject
  private transient WahlDAO wahlDao;

  @Override
  protected void persistiere(Collection<EmailVorlage> neueEntities, EmailVorlageExchangeContext emailVorlageExchangeContext,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    for (EmailVorlage emailVorlage : neueEntities) {
      emailVorlage.setEmailLayout(findOrCreateEmailLayout(emailVorlage, bericht));
      emailVorlage.setWahltermin(wahlterminDao.attach(emailVorlageExchangeContext.getWahltermin()));
      emailVorlage.setWahl(wahlDao.attach(emailVorlageExchangeContext.getWahl()));
      emailVorlageDao.persist(emailVorlage);
    }
  }

  private EmailLayout findOrCreateEmailLayout(EmailVorlage emailVorlage, StringBuilder bericht) {
    EmailLayout emailLayoutInDatei = emailVorlage.getEmailLayout();
    if (emailLayoutInDatei == null) {
      return null;
    }
    EmailLayout emailLayout = null;
    try {
      emailLayout = emailLayoutDao.findByBezeichnung(emailLayoutInDatei.getBezeichnung());
      bericht.append(getMessage("email.vorlage.import.bericht.layout.ignoriert", emailVorlage.getBezeichnung(),
          emailLayoutInDatei.getBezeichnung()));
    }
    catch (NoResultException e) {
      emailLayout = createAndSaveEmailLayout(emailLayoutInDatei);
      bericht.append(getMessage("email.vorlage.import.bericht.layout.importiert", emailVorlage.getBezeichnung(),
          emailLayoutInDatei.getBezeichnung()));
    }
    bericht.append("\n");
    return emailLayout;
  }

  private EmailLayout createAndSaveEmailLayout(EmailLayout emailLayoutInDatei) {
    EmailLayout emailLayout = new EmailLayout();
    emailLayout.setBezeichnung(emailLayoutInDatei.getBezeichnung());
    emailLayout.setInhalt(emailLayoutInDatei.getInhalt());
    if (emailLayoutInDatei.getVerwendungTyp().isExklusiv() && emailLayoutDao.findByCountAll() == 0) {
      // NOTE: Exklusiven VerwendungTyp nur importieren, wenn kein anderes E-Mail-Layout vorhanden ist
      emailLayout.setVerwendungTyp(emailLayoutInDatei.getVerwendungTyp());
    }
    emailLayoutCreate.save(emailLayout);
    return emailLayout;
  }

  @Override
  protected void aktualisiere(EmailVorlage entityInDatei,
      EmailVorlage entityInDatenbank,
      EmailVorlageExchangeContext emailVorlageExchangeContext,
      DateiImportBerichtCustomData dateiImportBerichtCustomData,
      StringBuilder bericht) {
    entityInDatenbank.setBezeichnung(entityInDatei.getBezeichnung());
    entityInDatenbank.setInhalt(entityInDatei.getInhalt());
    entityInDatenbank.setEmailLayout(findOrCreateEmailLayout(entityInDatei, bericht));
    entityInDatenbank.setWahltermin(wahlterminDao.attach(entityInDatei.getWahltermin()));
    entityInDatenbank.setWahl(wahlDao.attach(entityInDatei.getWahl()));
  }

  @Override
  protected void loescheAusDatenbank(Collection<EmailVorlage> entitiesInDb, EmailVorlageExchangeContext emailVorlageExchangeContext,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    for (EmailVorlage emailVorlage : entitiesInDb) {
      emailVorlageDao.remove(emailVorlage);
    }
  }

  @Override
  protected List<EmailVorlage> getAllEntitiesInDB(EmailVorlageExchangeContext emailVorlageExchangeContext) {
    return emailVorlageDao.findByWahlterminOrderByBezeichnung(emailVorlageExchangeContext.getWahltermin());
  }

  @Override
  protected Function<EmailVorlage, EmailVorlageUK> getEntityToEntityTKFunction() {
    return EmailVorlageUK.getEmailVorlageToUKFunction();
  }

  @Override
  protected void validiere(Violations violations, List<EmailVorlage> emailVorlagen, EmailVorlageExchangeContext emailVorlageExchangeContext,
      ImportOptions importOptions) {
    for (EmailVorlage emailVorlage : emailVorlagen) {
      validateEntity(violations, emailVorlage, emailVorlage.getEmailVorlageTK());
    }
  }

  @Override
  protected void erstelleBericht(List<EmailVorlage> emailVorlages, EmailVorlageExchangeContext emailVorlageExchangeContext,
      ImportOptions importOptions, StringBuilder bericht, boolean vorab) {
    // nichts zu tun
  }

  @Override
  protected ImportExchange<List<EmailVorlage>, EmailVorlageExchangeContext> getExchange() {
    return emailVorlageImportExchange;
  }

  @Override
  protected Meta getMetaForEntityInternal() {
    return emailVorlageMeta;
  }
}
