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

import de.ivu.elect.business.entschaedigung.boundary.EntschaedigungToCalculateParameters;
import de.ivu.elect.business.entschaedigung.entity.Entschaedigung;
import de.ivu.elect.business.entschaedigung.entity.EntschaedigungsartKriteriumEinsatzfunktion;
import de.ivu.elect.business.entschaedigung.entity.EntschaedigungsartKriteriumEinsatzort;
import de.ivu.elect.business.person.entity.CorePersonendatenArt;
import de.ivu.elect.business.person.entity.Personendaten;
import de.ivu.elect.business.person.entity.PersonendatenArt;
import de.ivu.elect.business.wahlausschuss.boundary.WahlausschussmitgliedDAO;
import de.ivu.elect.business.wahlausschuss.entity.Wahlausschussmitglied;
import de.ivu.elect.business.wahlausschuss.entity.Wahlausschussrolle;

import javax.annotation.Nullable;
import javax.inject.Inject;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Set;

import static de.ivu.elect.jee.entity.EntityUtil.castTo;
import static java.util.Collections.emptyList;
import static java.util.stream.Collectors.toSet;

// NOTE ELECTMUC-1285, dass WahlausschussEntschaedigung vorerst weiterverwendet wird, so dass dieser
// Calculator zwar schon korrekt implementiert ist, aber aktuell nie verwendet wird.
public class WahlausschussmitgliedEntschaedigungCalculator extends AbstractPersonendatenEntschaedigungCalculator {

  @Inject
  private transient WahlausschussmitgliedDAO wahlausschussmitgliedDAO;

  public WahlausschussmitgliedEntschaedigungCalculator() {
    super();
  }

  @Override
  @SuppressWarnings("unchecked")
  public PersonendatenArt getSupportedPersonendatenArt() {
    return CorePersonendatenArt.WAHLAUSSCHUSSMITGLIED;
  }

  @Override
  public Collection<EntschaedigungsartKriteriumEinsatzort> getSupportedEinsatzorte() {
    return emptyList();
  }

  @Override
  public Collection<EntschaedigungsartKriteriumEinsatzfunktion> getSupportedEinsatzfunktionen() {
    Collection<EntschaedigungsartKriteriumEinsatzfunktion> result = new ArrayList<>();
    result.add(Wahlausschussrolle.VORSITZENDER);
    result.add(Wahlausschussrolle.VORSITZENDER_STELLVERTRETEND);
    result.add(Wahlausschussrolle.SCHRIFTFUEHRER);
    result.add(Wahlausschussrolle.SCHRIFTFUEHRER_STELLVERTRETEND);
    result.add(Wahlausschussrolle.BEISITZER);
    result.add(Wahlausschussrolle.BEISITZER_STELLVERTRETEND);
    result.add(Wahlausschussrolle.HILFSKRAFT);

    return result;
  }

  @Override
  protected boolean isEntschaedigungZulaessig(Personendaten personendaten, Entschaedigung entschaedigung, EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
    return super.isEntschaedigungZulaessig(personendaten, entschaedigung, entschaedigungToCalculateParameters) && personendaten.isInstanceOf(Wahlausschussmitglied.class);
  }

  @Override
  protected Set<Personendaten> findAllPersonendaten(EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
    // Immer alle Personendaten holen, ein (umständliches) Vorfiltern anhand der Parameter lohnt nicht, vgl. WahlhelferEntschaedigungCalculator#findAllPersonendaten. Alle
    // berechneten Entschädigungen werden anschließend sowieso nochmals anhand der Parameter gefiltert!
    return findAllWahlausschussmitgliedByWahl(entschaedigungToCalculateParameters);
  }

  private Set<Personendaten> findAllWahlausschussmitgliedByWahl(EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
    return wahlausschussmitgliedDAO.findByWahl(entschaedigungToCalculateParameters.getWahl()).stream().collect(toSet());
  }

  @Override
  @Nullable
  protected BigDecimal calculateGesamtbetragZulaessigByEinsatzOrNull(Personendaten personendaten, Entschaedigung entschaedigung,
      EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
    if (personendaten.isInstanceOf(Wahlausschussmitglied.class)) {
      return calculateGesamtbetragZulaessigByEinsatzOrNull(castTo(personendaten, Wahlausschussmitglied.class), entschaedigung, entschaedigungToCalculateParameters);
    }

    return null;
  }

  @Nullable
  private BigDecimal calculateGesamtbetragZulaessigByEinsatzOrNull(Wahlausschussmitglied wahlausschussmitglied, Entschaedigung entschaedigung,
      EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
    if (matchesKriteriumEinsatz(wahlausschussmitglied, entschaedigung, entschaedigungToCalculateParameters)) {
      return calculateGesamtbetragZulaessigByAnzahlOrNull(wahlausschussmitglied, entschaedigung, entschaedigungToCalculateParameters);
    }

    return null;
  }

  private boolean matchesKriteriumEinsatz(Wahlausschussmitglied wahlausschussmitglied, Entschaedigung entschaedigung, EntschaedigungToCalculateParameters entschaedigungToCalculateParameters) {
    return entschaedigung.matchesKriteriumEinsatz(EntschaedigungsartKriteriumEinsatzort.IRRELEVANT, wahlausschussmitglied.getWahlausschussrolle());
  }
}
