
package de.ivu.elect.core.exchange.mapper;

import java.io.Serializable;

import javax.inject.Inject;

import de.ivu.elect.business.ergebnis.entity.Stimmenart;
import de.ivu.elect.business.gebietsbaum.entity.Gebiet;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppeimgebiet.entity.GruppeImGebiet;
import de.ivu.elect.business.kandidatur.entity.Ersatzkandidatur;
import de.ivu.elect.business.kandidatur.entity.Kandidatur;
import de.ivu.elect.business.kandidatur.entity.KandidaturArt;
import de.ivu.elect.business.kandidatur.entity.Listenkandidatur;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.wahlvorschlag.entity.ReferendumOption;
import de.ivu.elect.business.wahlvorschlag.entity.Wahlvorschlag;
import de.ivu.elect.exchange.EntityMapper;
import de.ivu.elect.exchange.gebietsbaum.mapper.GebietMapperUtil;
import de.ivu.elect.interfaces.core.GebietReferenz;
import de.ivu.elect.interfaces.core.GruppeImGebietReferenz;
import de.ivu.elect.interfaces.core.GruppeReferenz;
import de.ivu.elect.interfaces.core.KandidaturReferenz;
import de.ivu.elect.interfaces.core.Person;
import de.ivu.elect.interfaces.core.PersonReferenz;
import de.ivu.elect.interfaces.core.WahlvorschlagArt;
import de.ivu.elect.interfaces.core.WahlvorschlagReferenz;

/**
 * Methoden, die sowohl von Import als auch Export Mapper verwendet werden
 */
public class WahlInternExternMapperUtil implements Serializable {

  private static final long serialVersionUID = 1L;

  @Inject
  private transient GebietMapperUtil gebietMapperUtil;

  public WahlInternExternMapperUtil() {
    super();
  }

  public WahlInternExternMapperUtil(GebietMapperUtil gebietMapperUtil) {
    super();

    this.gebietMapperUtil = gebietMapperUtil;
  }

  public <P extends Person> PersonReferenz mappePersonendatenZuReferenz(P person) {
    return createPersonReferenz(EntityMapper.createIdInDatei(person));
  }

  public PersonReferenz mappePersonendatenZuReferenz(Personendaten personendaten) {
    return createPersonReferenz(EntityMapper.createIdInDatei(personendaten));
  }

  private PersonReferenz createPersonReferenz(Long id) {
    PersonReferenz personReferenz = new PersonReferenz();
    personReferenz.setId(id);

    return personReferenz;
  }

  public KandidaturReferenz mappeKandidaturZuReferenz(Kandidatur kandidatur) {
    if (kandidatur == null) {
      return null;
    }

    KandidaturReferenz result = new KandidaturReferenz();
    result.setKandidaturArt(mappe(kandidatur.getKandidaturArt()));
    result.setGruppeImGebietReferenz(createGruppeImGebietReferenz(kandidatur.getGruppeImGebiet()));

    if (kandidatur.isListenkandidatur()) {
      Listenkandidatur listenkandidatur = kandidatur.castTo(Listenkandidatur.class).getEntity();

      result.setListenposition(listenkandidatur.getRelativePosition());
    } else if (kandidatur.isErsatzkandidatur()) {
      Ersatzkandidatur ersatzkandidatur = kandidatur.castTo(Ersatzkandidatur.class).getEntity();

      result.setUebergeordneteKandidatur(mappeKandidaturZuReferenz(ersatzkandidatur.getUebergeordneteKandidatur()));
    }

    return result;
  }

  public WahlvorschlagReferenz mappeWahlvorschlagReferenz(Wahlvorschlag wahlvorschlag) {
    WahlvorschlagArt wahlvorschlagArt = bestimmeWahlvorschlagArt(wahlvorschlag);

    WahlvorschlagReferenz result = new WahlvorschlagReferenz(wahlvorschlagArt, createGruppeImGebietReferenz(wahlvorschlag.getGruppeImGebiet()));

    // abwärtskompatibilität ELECT-2413 irgendwann(tm) mal entfernen
    result.setPosition(0L);

    return result;
  }

  private WahlvorschlagArt bestimmeWahlvorschlagArt(Wahlvorschlag wahlvorschlag) {
    if (wahlvorschlag.isListe()) {
      return WahlvorschlagArt.LISTE;
    }

    if (wahlvorschlag.isDirektkandidat()) {
      return WahlvorschlagArt.DIREKTKANDIDAT;
    }

    if (wahlvorschlag.isReferendumOption()) {
      return WahlvorschlagArt.REFERENDUM_OPTION;
    }

    throw new IllegalArgumentException("Unbekannter Wahlvorschlagstyp: " + wahlvorschlag);
  }

  public de.ivu.elect.interfaces.core.ReferendumOption mappeReferendum(ReferendumOption referendumOption) {
    if (referendumOption == null) {
      return null;
    }
    de.ivu.elect.interfaces.core.ReferendumOption result = new de.ivu.elect.interfaces.core.ReferendumOption();
    result.setWahlvorschlagReferenz(new WahlvorschlagReferenz(WahlvorschlagArt.REFERENDUM_OPTION, createGruppeImGebietReferenz(referendumOption.getGruppeImGebiet())));
    result.setPosition(referendumOption.getPosition());
    result.setLabel(referendumOption.getLabel());
    result.setKurzbezeichnung(referendumOption.getKurzbezeichnung());
    //  bei weiteren Attributen BEACHTE AUCH WahlInternExternMapper.mappeWahlvorschlaege
    return result;
  }

  public GruppeImGebietReferenz createGruppeImGebietReferenz(GruppeImGebiet gruppeImGebietIntern) {
    if (gruppeImGebietIntern == null) {
      return null;
    }
    return getGruppeImGebietReferenz(gruppeImGebietIntern.getGruppe(), gruppeImGebietIntern.getGebiet());
  }

  public GruppeImGebietReferenz getGruppeImGebietReferenz(Gruppe gruppe, Gebiet gebiet) {
    return createGruppeImGebietReferenz(gruppe.getSchluessel(), gebiet.getNummer(), gebiet.getGebietsart().getName());
  }

  private GruppeImGebietReferenz createGruppeImGebietReferenz(String gruppenschluessel, String gebietNummer, String gebietsart) {
    GruppeImGebietReferenz result = new GruppeImGebietReferenz();
    result.setGruppe(createGruppeReferenz(gruppenschluessel));
    result.setGebiet(createGebietReferenz(gebietNummer, gebietsart));
    return result;
  }

  protected de.ivu.elect.interfaces.core.KandidaturArt mappe(KandidaturArt kandidaturArt) {
    return de.ivu.elect.interfaces.core.KandidaturArt.valueOf(kandidaturArt.name());
  }

  public de.ivu.elect.interfaces.core.Stimmenart mappeStimmenart(Stimmenart stimmenart) {
    return de.ivu.elect.interfaces.core.Stimmenart.valueOf(stimmenart.name());
  }

  public GruppeReferenz createGruppeReferenz(String schluessel) {
    return gebietMapperUtil.createGruppeReferenz(schluessel);
  }

  private GebietReferenz createGebietReferenz(String nummer, String gebietsart) {
    return gebietMapperUtil.createGebietReferenz(nummer, gebietsart);
  }

  public GebietReferenz createGebietReferenz(Gebiet gebiet) {
    return gebietMapperUtil.createGebietReferenz(gebiet);
  }
}
