package de.ivu.elect.business.veranstaltung.control;

import java.util.List;

import javax.ejb.Stateless;
import javax.enterprise.inject.Instance;
import javax.inject.Inject;
import javax.persistence.NoResultException;

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

import de.ivu.elect.business.datei.entity.DateiImportBerichtCustomData;
import de.ivu.elect.business.exchange.control.DateienImportierenBackgroundService;
import de.ivu.elect.business.exchange.entity.DateiImportArt;
import de.ivu.elect.business.exchange.entity.DateienImportierenBackgroundServiceContext;
import de.ivu.elect.business.exchange.entity.DateienImportierenBackgroundServiceImportContext;
import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.mandant.entity.EntityPKMitMandant;
import de.ivu.elect.business.system.control.AbstractWahlOderWahlterminMultipleCronTimerAsync;
import de.ivu.elect.business.system.entity.SystemLogQuelle;
import de.ivu.elect.business.veranstaltung.boundary.TeilnahmeImporter;
import de.ivu.elect.business.veranstaltung.boundary.VeranstaltungImporter;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.business.wahl.entity.WahlOderWahlterminPK;
import de.ivu.elect.business.wahl.entity.Wahltermin;
import de.ivu.elect.jee.cdi.BeanManagerUtil;
import de.ivu.elect.jee.exchange.ImportOptions;


import static de.ivu.elect.business.wahl.entity.WahlParameterWerte.VERANSTALTUNG_IMPORT_ERFOLGREICH_VERZEICHNIS;
import static de.ivu.elect.business.wahl.entity.WahlParameterWerte.VERANSTALTUNG_IMPORT_FEHLER_VERZEICHNIS;
import static de.ivu.elect.business.wahl.entity.WahlParameterWerte.VERANSTALTUNG_IMPORT_VERZEICHNIS;
import static java.util.Arrays.asList;

/**
 *  on 03.01.2017.
 *
 * NICHT ALS VORLAGE VERWENDEN, BESTEHT AUS ZWEI IMPORTERN
 */
@Stateless
public class VeranstaltungImportAsync extends AbstractWahlOderWahlterminMultipleCronTimerAsync {

  private static final Logger LOG = LoggerFactory.getLogger(VeranstaltungImportAsync.class);

  @Inject
  DateienImportierenBackgroundService dateienImportierenBackgroundService;

  @Inject
  Instance<VeranstaltungImportFormatResolver> formatResolvers;


  @Override
  public SystemLogQuelle getSystemLogQuelle() {
    return SystemLogQuelle.VERANSTALTUNG_IMPORTER;
  }

  @Override
  protected void handleWahlOderWahltermin(WahlOderWahlterminPK wahlOderWahlterminPK) {
    LOG.info("VeranstaltungImportAsync.handle " + "wahlUndWahlterminPK = [" + wahlOderWahlterminPK + "]");

    EntityPKMitMandant entityPKMitMandant = EntityPKMitMandant.from(wahlOderWahlterminPK);
    if (wahlOderWahlterminPK.isWahlPK()) {
      LOG.info("Wahl: " + wahlOderWahlterminPK.getWahlPK());
      while (dateienImportierenBackgroundService.importiere(wahlOderWahlterminPK.getWahlPK(), createContext(entityPKMitMandant))) {
        LOG.info("VeranstaltungImportAsync.handle - weiterer Aufruf");
      }
    } else {
      LOG.info("Wahltermin: " + wahlOderWahlterminPK.getWahlterminPK());
      while (dateienImportierenBackgroundService.importiere(wahlOderWahlterminPK.getWahlterminPK(), createContext(entityPKMitMandant))) {
        LOG.info("VeranstaltungImportAsync.handle - weiterer Aufruf");
      }

    }

    LOG.info("VeranstaltungImportAsync.handle " + "wahlUndWahlterminPK = [" + wahlOderWahlterminPK + "]" + " - done");

  }

  protected DateienImportierenBackgroundServiceContext createContext(EntityPKMitMandant mandantPK) {
    return new DateienImportierenBackgroundServiceContext(VERANSTALTUNG_IMPORT_VERZEICHNIS,
        VERANSTALTUNG_IMPORT_ERFOLGREICH_VERZEICHNIS, VERANSTALTUNG_IMPORT_FEHLER_VERZEICHNIS, getSystemLogQuelle(),
        createImportContexts(mandantPK));

  }

  protected List<DateienImportierenBackgroundServiceImportContext> createImportContexts(EntityPKMitMandant mandantPK) {
    return asList(new DateienImportierenBackgroundServiceImportContext(mandantPK, VeranstaltungImporter.class, formatResolvers, DateiImportArt.VERANSTALTUNG_IMPORT,
        w -> {
          Wahltermin wahltermin;
          Wahl wahl;
          Gebiet gebiet;

          if (w.isInstanceOfWahl()) {
            wahl = w.castTo(Wahl.class).getEntity();
            wahltermin = wahl.getWahltermin();
            try {
              gebiet = BeanManagerUtil.getBeanByClass(GebietDAO.class).findByWahlWurzelgebiet(wahl);
            } catch (NoResultException nre) {
              LOG.warn("Kein oberstes Gebiet für Wahl: " + wahl);
              gebiet = null;
            }
          } else {
            wahltermin = w.castTo(Wahltermin.class).getEntity();
            wahl = null;
            try {
              gebiet = BeanManagerUtil.getBeanByClass(GebietDAO.class).findByWahlterminWurzelgebiet(wahltermin);
            } catch (NoResultException nre) {
              LOG.warn("Kein oberstes Gebiet für Wahltermin: " + wahltermin);
              gebiet = null;
            }
          }

          return new VeranstaltungExchangeContext(wahltermin, wahl, gebiet);

        }, ImportOptions.NEUE_DATEN_ANLEGEN_BESTEHENDE_DATEN_AKTUALISIEREN, new DateiImportBerichtCustomData()

    ),

        new DateienImportierenBackgroundServiceImportContext(mandantPK, TeilnahmeImporter.class, formatResolvers, DateiImportArt.TEILNAHME_IMPORT,
            w -> {
              Wahltermin wahltermin;
              Wahl wahl;
              Gebiet gebiet;

              if (w.isInstanceOfWahl()) {
                wahl = w.castTo(Wahl.class).getEntity();
                wahltermin = wahl.getWahltermin();
                try {
                  gebiet = BeanManagerUtil.getBeanByClass(GebietDAO.class).findByWahlWurzelgebiet(wahl);
                } catch (NoResultException nre) {
                  LOG.warn("Kein oberstes Gebiet für Wahl: " + wahl);
                  gebiet = null;
                }
              } else {
                wahltermin = w.castTo(Wahltermin.class).getEntity();
                wahl = null;
                try {
                  gebiet = BeanManagerUtil.getBeanByClass(GebietDAO.class).findByWahlterminWurzelgebiet(wahltermin);
                } catch (NoResultException nre) {
                  LOG.warn("Kein oberstes Gebiet für Wahltermin: " + wahltermin);
                  gebiet = null;
                }
              }

              return new TeilnahmeExchangeContext(wahltermin, wahl, gebiet);

            }, ImportOptions.NEUE_DATEN_ANLEGEN_BESTEHENDE_DATEN_UNVERAENDERT_LASSEN,
            new DateiImportBerichtCustomData()

        )
        );

  }

  @Override
  protected EntityPKMitMandant bestimmeMandantAusPayload(WahlOderWahlterminPK wahlOderWahlterminPK) {
    return bestimmeMandant(wahlOderWahlterminPK);
  }

  @Override
  public Logger getLog() {
    return LOG;
  }
}
