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

import java.util.List;

import javax.ejb.Stateless;
import javax.inject.Inject;

import de.ivu.elect.business.datei.entity.DateiImport;
import de.ivu.elect.business.datei.entity.DateiImportBerichtCustomData;
import de.ivu.elect.business.ergebnis.control.AbstractErgebnisImportContext;
import de.ivu.elect.business.ergebnis.control.StimmenCreate;
import de.ivu.elect.business.ergebnis.control.StimmenImportContext;
import de.ivu.elect.business.ergebnis.control.StimmenImportExchange;
import de.ivu.elect.business.ergebnis.entity.AbstractErgebnis;
import de.ivu.elect.business.ergebnis.entity.Ergebnis;
import de.ivu.elect.business.ergebnis.entity.Stimmen;
import de.ivu.elect.business.ergebnis.entity.StimmenMeta;
import de.ivu.elect.business.exchange.control.AbstractImporter;
import de.ivu.elect.business.exchange.control.ImportExchange;
import de.ivu.elect.business.exchange.control.MappingException;
import de.ivu.elect.jee.exchange.Violations;
import de.ivu.elect.business.exchange.entity.ImportUpdateReport;
import de.ivu.elect.business.gruppeimgebiet.control.AbstractGruppeImGebietCache;
import de.ivu.elect.business.gruppeimgebiet.control.GruppeImGebietCacheFactory;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.wahl.boundary.WahlDAO;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.entity.Meta;
import de.ivu.elect.jee.exchange.ImportOptions;

@Stateless
/**
 * WARNUNG: Diese Klasse nicht als Vorlage für neue Importer verwenden!!!
 */
public class StimmenImporter
    extends
      AbstractImporter<List<Stimmen>, StimmenImportContext, DateiImportBerichtCustomData> {

  @Inject
  private transient StimmenMeta stimmenMeta;

  @Inject
  private transient StimmenImportExchange stimmenImportExchange;

  @Inject
  private transient StimmenImportReport stimmenImportReport;

  @Inject
  private transient StimmenImportValidator stimmenImportValidator;

  @Inject
  private transient ErgebnisDAO ergebnisDAO;

  @Inject
  private transient WahlDAO wahlDAO;

  @Inject
  private transient GruppeImGebietCacheFactory gruppeImGebietCacheFactory;

  @Inject
  private transient StimmenCreate stimmenCreate;

  @Inject
  private transient StimmenEdit stimmenEdit;

  /*
   * Cf. ELECT-522: Beim Import der Vorperiodenergebnisse sollen fehlende Gruppen zu Übrige kumulieren
   */
  @Override
  protected List<Stimmen> readImportObject(DateiImport dateiImport, StimmenImportContext context)
      throws MappingException {
    List<Stimmen> result = super.readImportObject(dateiImport, context);
    result = postRead(result, context);
    return result;
  }

  protected List<Stimmen> postRead(List<Stimmen> result, StimmenImportContext context) {
    // nichts zu tun
    return result;
  }

  @Override
  protected ImportUpdateReport createImportUpdateReport(List<Stimmen> importStimmen, Violations violations,
      StimmenImportContext context, ImportOptions importOptions, StringBuilder bericht) {
    return stimmenImportReport.createImportUpdateReport(importStimmen, violations, context, importOptions, bericht);
  }

  @Override
  protected void validiere(Violations violations, List<Stimmen> importObject, StimmenImportContext context, ImportOptions importOptions) {
    stimmenImportValidator.validiere(violations, importObject, context);
  }

  @Override
  protected ImportExchange<List<Stimmen>, StimmenImportContext> getExchange() {
    return stimmenImportExchange;
  }

  @Override
  public Meta getMetaForEntityInternal() {
    return stimmenMeta;
  }

  @Override
  protected void anlegenWennNichtVorhanden(List<Stimmen> stimmenInDatei, StimmenImportContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {

    Ergebnis ergebnis = findeErgebnis(context);
    Wahl wahl = wahlDAO.attach(ergebnis.getWahl());
    AbstractGruppeImGebietCache gruppeImGebietCache = gruppeImGebietCacheFactory
        .createNewGruppeImGebietCompleteHierarchyCache(wahl);

    for (Stimmen stimmen : stimmenInDatei) {
      // Stimmen von Gruppen, die nicht in der aktuellen Wahl vorhanden sind ignorieren
      if (gruppeImGebietCache.isGruppeVorhanden(stimmen.getGruppe().getGruppeTK())) {

        exchangeGruppeImGebietWithGruppeImGebietFromDb(wahl, stimmen, gruppeImGebietCache);

        stimmen.setErgebnis(ergebnis);
        stimmenCreate.save(stimmen);
      }
    }
  }

  private Ergebnis findeErgebnis(AbstractErgebnisImportContext context) {
    return AbstractErgebnis.getErgebnisZurWahlNachErgebnisart(context.getZiel(), context.getWahl(), ergebnisDAO);
  }

  protected void exchangeGruppeImGebietWithGruppeImGebietFromDb(Wahl wahl, Stimmen stimmen,
      AbstractGruppeImGebietCache gruppeImGebietCache) {
    GruppeImGebiet gruppeImGebiet = findOrCreateGruppeImGebiet(stimmen, gruppeImGebietCache);
    stimmen.setGruppe(gruppeImGebiet.getGruppe());
    stimmen.setGebiet(gruppeImGebiet.getGebiet());
  }

  protected GruppeImGebiet findOrCreateGruppeImGebiet(Stimmen stimmen, AbstractGruppeImGebietCache gruppeImGebietCache) {
    return gruppeImGebietCache.findOrCreate(stimmen.getGruppeImGebietTK());
  }

  @Override
  protected void aktualisiereBestehendenDaten(List<Stimmen> importObject, StimmenImportContext context,
      DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    // nichts zu tun, da beim Import von Stimmen immer alle Stimmen entfernt und dann neu angelegt werden 
  }

  @Override
  protected void loescheBestehendenDatenWennNichtInImportDatenVorhanden(List<Stimmen> importObject,
      StimmenImportContext context, DateiImportBerichtCustomData dateiImportBerichtCustomData, StringBuilder bericht) {
    stimmenEdit.deleteByErgebnis(findeErgebnis(context));
  }

  @Override
  protected void erstelleBericht(List<Stimmen> importObject, StimmenImportContext context, ImportOptions importOptions,
      StringBuilder bericht, boolean vorab) {
    // do nothing
  }
}
