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

import de.ivu.elect.business.ergebnis.entity.Stimmenart;
import de.ivu.elect.business.gruppe.entity.PolitischeGruppe;

/**
 *  on 05.04.2016.
 * Lehmermittelberechnung
 */
public class BrunosRelativesMassLehmerMittel implements StimmenAbweichungMass  {
    //Exponent im Nenner der Massberechnung; je größer desto stärker kleine parteien gewichtet
    private final double gewichtungKleinerParteien;

    public BrunosRelativesMassLehmerMittel (double gewichtungKleinerParteien) {
        this.gewichtungKleinerParteien = gewichtungKleinerParteien;
    }
    @Override
    public double berechneAbweichungImGebiet(AbweichungMassStimmenProvider stimmenProvider) {
        //benötigt für LehmerMittelBerechnung
        double sumdenominator =0;
        double sumnominator = 0;

        for (Stimmenart stimmabgabeart : stimmenProvider.getStimmenarten()) {

            double gueltigeEingegeben = (double) Math.max(1, stimmenProvider.getAnzahlGueltigeStimmenEingegeben(stimmabgabeart));
            double gueltigeHochgerechnet = (double) Math.max(1, stimmenProvider.getAnzahlGueltigeStimmenHochgerechnet(stimmabgabeart));

            for (PolitischeGruppe politischeGruppe : stimmenProvider.getPolitischeGruppen()) {
                double prozentEingegeben = stimmenProvider.getAnzahlStimmenEingegeben(politischeGruppe, stimmabgabeart) / gueltigeEingegeben;
                double prozentHochgerechnet = stimmenProvider.getAnzahlStimmenHochgerechnet(politischeGruppe, stimmabgabeart) / gueltigeHochgerechnet;
                double mass=0;
                double min=0;
                //es werden 4 Fälle unterschieden: wenn keine Eingabe erfolgt soll 0 ausgegeben und im Mittelwert nicht berücksichtigt werden
                if(prozentEingegeben!=0 && prozentHochgerechnet!=0){
                    min = Math.min(prozentEingegeben, prozentHochgerechnet);
                    mass = Math.abs(prozentEingegeben - prozentHochgerechnet) / Math.pow(min, gewichtungKleinerParteien); //Mass-Formel

                    sumnominator = sumnominator + Math.pow(mass, 1.5); // hier wird die LehmerMittel Berechnung vorbereitet mit p=1,5
                    sumdenominator = sumdenominator + Math.pow(mass, .5);
                }
                //hier wird die Stimmanzahl von 0 auf 1 gesetzt damit weitergrechnet werden kann
                else if (prozentEingegeben==0 && prozentHochgerechnet!=0){
                    min = 1/gueltigeEingegeben;
                    mass = Math.abs(prozentEingegeben - prozentHochgerechnet) / Math.pow(min, gewichtungKleinerParteien); //Mass-Formel

                    sumnominator = sumnominator + Math.pow(mass, 1.5); // hier wird die LehmerMittel Berechnung vorbereitet mit p=1,5
                    sumdenominator = sumdenominator + Math.pow(mass, .5);
                }
                //hier wird die Stimmanzahl von 0 auf 1 gesetzt damit weitergrechnet werden kann
                else if (prozentEingegeben!=0 && prozentHochgerechnet==0){
                    min = 1/prozentHochgerechnet;
                    mass = Math.abs(prozentEingegeben - prozentHochgerechnet) / Math.pow(min, gewichtungKleinerParteien); //Mass-Formel

                    sumnominator = sumnominator + Math.pow(mass, 1.5); // hier wird die LehmerMittel Berechnung vorbereitet mit p=1,5
                    sumdenominator = sumdenominator + Math.pow(mass, .5);
                }
                else{//so wird verhindert das der sumdenominator jemals 0 werden kann
                    sumnominator += 0;
                    sumdenominator = 1;
                }
            }
        }
        return 100*(sumnominator / Math.max(sumdenominator,0.0000000000000000000000000000000000000000001d));
        // dadurch möchte ich verhindern, dass sumdenominator nicht 0 annimmt und da sumdenominator sehr kleine Zahlen annehmen kann, wählte ich diese Zahl,
        //nicht schön, aber nicht mehr genug zeit um das zu verbessern.
    }

    @Override
    public String getMessageKey() {
        return "stimmen.abweichung.mass.relativ.lehmer.mittel";
    }
}


//hier werden die 4 fälle nicht betrachtet
/*@Override
    public double berechneAbweichungImGebiet(AbweichungMassStimmenProvider stimmenProvider) {
        //benötigt für LehmerMittelBerechnung
        double sumdenominator =0;
        double sumnominator = 0;

        for (Stimmenart stimmabgabeart : stimmenProvider.getStimmenarten()) {

            double gueltigeEingegeben = (double) Math.max(1, stimmenProvider.getAnzahlGueltigeStimmenEingegeben(stimmabgabeart));
            double gueltigeHochgerechnet = (double) Math.max(1, stimmenProvider.getAnzahlGueltigeStimmenHochgerechnet(stimmabgabeart));

            for (PolitischeGruppe politischeGruppe : stimmenProvider.getPolitischeGruppen()) {
                double prozentEingegeben = stimmenProvider.getAnzahlStimmenEingegeben(politischeGruppe, stimmabgabeart) / gueltigeEingegeben;
                double prozentHochgerechnet = stimmenProvider.getAnzahlStimmenHochgerechnet(politischeGruppe, stimmabgabeart) / gueltigeHochgerechnet;


                if(prozentEingegeben!=0 && prozentHochgerechnet!=0){
                    double min = Math.min(prozentEingegeben, prozentHochgerechnet);
                    double mass = Math.abs(prozentEingegeben - prozentHochgerechnet) / Math.pow(min, gewichtungKleinerParteien); //Mass-Formel


                    sumnominator = sumnominator + Math.pow(mass, 1.5); // hier wird die LehmerMittel Berechnung vorbereitet mit p=1,5
                    sumdenominator = sumdenominator + Math.pow(mass, .5);
                }
            }
        }
        return 100*(sumnominator / sumdenominator);
    }*/

