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

import java.util.Set;

import javax.enterprise.inject.Specializes;
import javax.inject.Inject;
import javax.persistence.NoResultException;

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

import de.ivu.elect.business.gebietsbaum.boundary.GebietDAO;
import de.ivu.elect.business.gebietsbaum.boundary.GebietUebernehmen;
import de.ivu.elect.business.gebietsbaum.boundary.GebietsartDAO;
import de.ivu.elect.business.gebietsbaum.boundary.WahldurchfuehrungsgebietFactory;
import de.ivu.elect.business.gebietsbaum.entity.AbstractGebiet;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gebietsbaum.entity.GebietUebernehmenContext;
import de.ivu.elect.business.gebietsbaum.entity.Gebietsart;
import de.ivu.elect.business.gebietsbaum.entity.GebietsartUK;
import de.ivu.elect.business.gebietsbaum.entity.Wahldurchfuehrungsgebiet;
import de.ivu.elect.business.wahl.boundary.WahlDAO;
import de.ivu.elect.business.wahl.boundary.WahlartDAO;
import de.ivu.elect.business.wahl.entity.Wahl;
import de.ivu.elect.jee.exception.ElectCommonException;
import de.ivu.elect.presentation.gebietsbaum.GebietNummerFormatter;
import de.ivu.elect.presentation.mandant.MandantNameFormatter;

@Specializes
public class WasGebietCreate extends CoreGebietCreate {

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

  @Inject
  private transient WahlDAO wahlDAO;

  @Inject
  private transient WahldurchfuehrungsgebietFactory wahldurchfuehrungsgebietFactory;

  @Inject
  private transient GebietsartDAO gebietsartDAO;

  @Inject
  private transient GebietDAO gebietDAO;

  @Inject
  private transient MandantNameFormatter mandantNameFormatter;

  @Inject
  private transient GebietNummerFormatter gebietNummerFormatter;

  @Inject
  private transient WahlartDAO wahlartDAO;

  @Inject
  private transient GebietUebernehmen gebietUebernehmen;

  @Override
  public void save(Gebiet entity) {
    Wahldurchfuehrungsgebiet wahldurchfuehrungsgebiet = entity.castTo(Wahldurchfuehrungsgebiet.class).getEntity();
    wahldurchfuehrungsgebiet.setWahlartBeiAufteilung(wahlartDAO.attach(wahldurchfuehrungsgebiet.getWahlartBeiAufteilung()));
    super.save(entity);
  }

  @Override
  public void saveFromView(Gebiet entity) {
    super.saveFromView(entity);

    createVerantwortlichBerichtetAn(entity);
  }

  public void createVerantwortlichBerichtetAn(Gebiet entity) {
    if (entity.getWahl() == null || entity.getUebergeordnetesGebiet() == null) {
      return;
    }

    Set<Wahl> zielWahlenBeiAufteilung = entity.getZielWahlenBeiAufteilung(wahlDAO, gebietDAO);

    for (Wahl zielWahl : zielWahlenBeiAufteilung) {
      if (isGebietInZielWahlBereitsVorhandenMandantenUnabhaengig(zielWahl, entity)) {
        throw new ElectCommonException("gebiet.anlegen.aufgeteilt.gebiet.bereits.vorhanden",
            mandantNameFormatter.formatiereName(zielWahl.getMandant()), gebietNummerFormatter.getDarstellung(entity));
      } else {
        LOG.info("Lege Gebiet auch in Wahl an: " + zielWahl);
        Wahldurchfuehrungsgebiet copy = wahldurchfuehrungsgebietFactory.create();

        GebietUebernehmenContext uebernehmenContext = new GebietUebernehmenContext(false /* nicht benötigt in ziel */, true, false /* lieber mal nicht */, true/*legacy*/, true/*legacy*/);
        gebietUebernehmen.kopierereGebietUnveraendert(entity, copy, uebernehmenContext);

        copy.setWahl(zielWahl);
        copy.setWahltermin(zielWahl.getWahltermin());
        copy.setVerantwortlicherMandant(null);
        copy.setGebietsart(findZielGebietsart(entity, zielWahl));
        copy.setUebergeordnetesGebiet(findeGebietInZielWahl(entity.getUebergeordnetesGebiet(), zielWahl));
        try {
          super.saveFromView(copy);
        } catch (Exception e) {
          throw new ElectCommonException("gebiet.anlegen.aufgeteilt.gebiet.anlegen.fehler", e,
              mandantNameFormatter.formatiereName(zielWahl.getMandant()), gebietNummerFormatter.getDarstellung(entity));
        }
      }
    }

  }

  private boolean isGebietInZielWahlBereitsVorhandenMandantenUnabhaengig(Wahl zielWahl, Gebiet entity) {
    return AbstractGebiet.findeGebietBeiAufteilungHandleWithCare(entity.getGebietTK(), zielWahl, gebietDAO, null /*mandantenunabhängig*/) != null;
  }

  private Gebiet findeGebietInZielWahl(Gebiet gebiet, Wahl zielWahl) {
    Gebiet result = AbstractGebiet.findeGebietBeiAufteilungHandleWithCare(gebiet, zielWahl, gebietDAO);
    if (result == null) {
      throw new ElectCommonException("gebiet.anlegen.aufgeteilt.uebergeordnetes.gebiet.nicht.gefunden",
          mandantNameFormatter.formatiereName(zielWahl.getMandant()), gebietNummerFormatter.getDarstellung(gebiet));
    }
    return result;
  }

  private Gebietsart findZielGebietsart(Gebiet entity, Wahl zielWahl) {
    try {
      return gebietsartDAO.findByUK(new GebietsartUK(entity.getGebietsart().getName(), zielWahl.getMandant().getMandantUK()));
    } catch (NoResultException nre) {
      throw new ElectCommonException("gebiet.anlegen.aufgeteilt.gebietsart.nicht.gefunden", mandantNameFormatter.formatiereName(zielWahl.getMandant()),
          entity.getGebietsart().getName());
    }
  }
}
