package de.ivu.elect.business.ergebnis.control.mass;

import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

import de.ivu.elect.business.ergebnis.entity.Stimmen;
import de.ivu.elect.business.ergebnis.entity.Stimmenart;
import de.ivu.elect.business.gruppe.entity.Gruppe;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;
import de.ivu.elect.business.gruppe.entity.SystemGruppe;
import de.ivu.elect.business.gruppe.entity.SystemGruppeEigenschaften;

/**
 *  on 16.03.2016.
 */
public class DefaultAbweichungMassStimmenProvider implements AbweichungMassStimmenProvider {

    private final Collection<Stimmen> hochgerechneteStimmen;

    private final Collection<Stimmen> erfassteStimmen;

    private final SystemGruppeEigenschaften systemGruppeEigenschaften;

    private Set<PolitischeGruppe> politischeGruppen;
    private Set<Stimmenart> stimmenarten;


    public DefaultAbweichungMassStimmenProvider(Collection<Stimmen> hochgerechneteStimmen, Collection<Stimmen> erfassteStimmen, SystemGruppeEigenschaften systemGruppeEigenschaften){
        this.hochgerechneteStimmen = hochgerechneteStimmen;
        this.erfassteStimmen = erfassteStimmen;
        this.systemGruppeEigenschaften = systemGruppeEigenschaften;
    }

    @Override
    public Collection<PolitischeGruppe> getPolitischeGruppen() {

        if (politischeGruppen==null){
            politischeGruppen = new HashSet<>();
            politischeGruppen.addAll(hochgerechneteStimmen.stream().map(Stimmen::getGruppe).filter(Gruppe::isPolitischeGruppe).map(g->g.castTo(PolitischeGruppe.class).getEntity()).collect(Collectors.toSet()));
            politischeGruppen.addAll(erfassteStimmen.stream().map(Stimmen::getGruppe).filter(Gruppe::isPolitischeGruppe).map(g->g.castTo(PolitischeGruppe.class).getEntity()).collect(Collectors.toSet()));
        }

        return politischeGruppen;
    }

    @Override
    public Collection<Stimmenart> getStimmenarten() {
        if (stimmenarten==null){
            stimmenarten = new HashSet<>();
            stimmenarten.addAll(hochgerechneteStimmen.stream().map(Stimmen::getStimmenart).collect(Collectors.toSet()));
            stimmenarten.addAll(erfassteStimmen.stream().map(Stimmen::getStimmenart).collect(Collectors.toSet()));
        }

        return stimmenarten;

    }

    @Override
    public Long getAnzahlStimmenHochgerechnet(PolitischeGruppe politischeGruppe, Stimmenart stimmenart) {
        return hochgerechneteStimmen.stream().filter(s->s.getStimmenart().equals(stimmenart)).filter(s->s.getGruppe().equals(politischeGruppe)).map(Stimmen::getAnzahl).findAny().orElse(0L);
    }

    @Override
    public Long getAnzahlStimmenEingegeben(PolitischeGruppe politischeGruppe, Stimmenart stimmenart) {
      return erfassteStimmen.stream().filter(s->s.getStimmenart().equals(stimmenart)).filter(s->s.getGruppe().equals(politischeGruppe)).map(Stimmen::getAnzahl).findAny().orElse(0L);
    }

    @Override
    public Long getAnzahlGueltigeStimmenHochgerechnet(Stimmenart stimmenart) {
      return hochgerechneteStimmen.stream().filter(s->s.getStimmenart().equals(stimmenart)).filter(s->systemGruppeEigenschaften.isGruppeEqualsSystemGruppe(s.getGruppe(), SystemGruppe.GUELTIGE)).map(Stimmen::getAnzahl).findAny().orElse(0L);
    }

    @Override
    public Long getAnzahlGueltigeStimmenEingegeben(Stimmenart stimmenart) {
      return erfassteStimmen.stream().filter(s->s.getStimmenart().equals(stimmenart)).filter(s->systemGruppeEigenschaften.isGruppeEqualsSystemGruppe(s.getGruppe(), SystemGruppe.GUELTIGE)).map(Stimmen::getAnzahl).findAny().orElse(0L);
    }
}
