package no.valg.valgnatt.database.hibernate;

import no.valg.valgnatt.database.GrunnlagsdataMockup;
import no.valg.valgnatt.database.Konstanter;
import no.valg.valgnatt.database.domene.ForeløpigEndeligOppgjør;
import no.valg.valgnatt.database.domene.OpptaltStatus;
import no.valg.valgnatt.database.domene.Valg;
import no.valg.valgnatt.database.domene.ValgType;
import no.valg.valgnatt.database.domene.ValgtingForhand;
import no.valg.valgnatt.database.geografi.Kommune;

import org.junit.Assert;
import org.junit.BeforeClass;
import org.junit.Test;

public class StemmekretsTest {

    private static final float FLOAT_DELTA = 0.0000001f;
    private static final float TIPROSENT = 0.1f;
    private static GrunnlagsdataMockup gdm;

    @BeforeClass
    public static void initialiser() {
        gdm = new GrunnlagsdataMockup();
        gdm.initialiser(ValgType.ST);
    }


    @Test
    public void beregnFrammoteProsentIaar_Uansett_Null() throws Exception {
        Stemmekrets stemmekrets = new Stemmekrets();
        Assert.assertEquals(null, stemmekrets.beregnFrammoteProsentIaar());
    }

    @Test
    public void getOSMax_SjekkTypeKonvertering() throws Exception {
        Stemmekrets stemmekrets = new Stemmekrets();
        stemmekrets.setOpptaltStatusMax(OpptaltStatus.ALLE_ENDELIG.getStatus());
        Assert.assertEquals(OpptaltStatus.ALLE_ENDELIG, stemmekrets.getOSMax());
    }

    @Test
    public void getOS() throws Exception {
        Stemmekrets stemmekrets = new Stemmekrets();
        stemmekrets.setOpptaltStatusMax(OpptaltStatus.ALLE_ENDELIG.getStatus());
        stemmekrets.setOpptaltStatus(OpptaltStatus.ALLE_FORELØPIG.getStatus());
        Assert.assertEquals(OpptaltStatus.ALLE_FORELØPIG, stemmekrets.getOS());
    }

    @Test
    public void getStemmekretser_ReturnerSegSelv() throws Exception {
        Stemmekrets stemmekrets = new Stemmekrets();
        StemmekretsId stemmekretsId = new StemmekretsId();
        stemmekretsId.setKretsnr("0123");
        stemmekrets.setId(stemmekretsId);
        Assert.assertEquals(stemmekrets, stemmekrets.getStemmekretser().get("0123"));
    }

    @Test
    public void getOverordnetOmråde_StavangerKommuneErOverordnetOmråde() throws Exception {
        Kommune stavangerKomm = gdm.getLand().getKommune(Konstanter.STAVANGER_KNR);
        Assert.assertEquals(stavangerKomm, stavangerKomm.getStemmekrets("0004").getOverordnetOmråde());
    }

    @Test
    public void getOverordnetOmråde_OsloHarBydelSomOverordnetOmråde() throws Exception {
        // Det er bare Oslo som har bydeler (i EVA Resultat)
        Kommune osloKomm = gdm.getLand().getKommune(Konstanter.OSLO_KNR);
        Assert.assertEquals(osloKomm.getBydel("1"), osloKomm.getStemmekrets("0101").getOverordnetOmråde());
    }

    @Test
    public void getUnderordnedeRapportOmråder_StemmekretserHarAldriUnderordnedeOmråder() {
        Stemmekrets stemmekrets = new Stemmekrets();
        Assert.assertEquals(0, stemmekrets.getUnderordnedeRapportOmråder().length);
    }

    // Gir en prosentandel av kommunen, basert på antall stemmeberettigede
    @Test
    public void andelAvKommune_25Prosent() {
        Kommune stavangerKomm = gdm.getLand().getKommune(Konstanter.STAVANGER_KNR);
        Stemmekrets defaultKrets = stavangerKomm.getStemmekrets(Konstanter.DEFAULT_KRETS);
        Assert.assertEquals(TIPROSENT, defaultKrets.andelAvKommune(), FLOAT_DELTA);
    }


    @Test
    public void erDefaultKrets_0001_Usann() throws Exception {
        Assert.assertEquals(false, gdm.getLand().getKommune(Konstanter.STAVANGER_KNR).getStemmekrets("0001").erDefaultKrets());
    }

    @Test
    public void erDefaultKrets_0000_Sann() throws Exception {
        Assert.assertEquals(true, gdm.getLand().getKommune(Konstanter.STAVANGER_KNR).getStemmekrets(Konstanter.DEFAULT_KRETS).erDefaultKrets());
    }

    @Test
    public void erOpptalt_BareForeløpigForhånd_ErOpptaltTilForeløpigForhånd() throws Exception {
        Assert.assertEquals(true, stemmekretsOppsettOpptaltstatus(OpptaltStatus.BARE_FHS_FORELØPIG).erOpptalt(ForeløpigEndeligOppgjør.FORELØPIG, ValgtingForhand.F));
    }

    @Test
    public void erOpptalt_AlleEndelig_ErOpptaltTilForeløpigForhånd() throws Exception {
        Assert.assertEquals(true, stemmekretsOppsettOpptaltstatus(OpptaltStatus.ALLE_ENDELIG).erOpptalt(ForeløpigEndeligOppgjør.FORELØPIG, ValgtingForhand.F));
    }

    @Test
    public void erOpptalt_AlleEndelig_ErOpptaltTilForeløpigValgting() throws Exception {
        Assert.assertEquals(true, stemmekretsOppsettOpptaltstatus(OpptaltStatus.ALLE_ENDELIG).erOpptalt(ForeløpigEndeligOppgjør.FORELØPIG, ValgtingForhand.V));
    }

    @Test
    public void erOpptalt_AlleEndelig_ErOpptaltTilForeløpigAlle() throws Exception {
        Assert.assertEquals(true, stemmekretsOppsettOpptaltstatus(OpptaltStatus.ALLE_ENDELIG).erOpptalt(ForeløpigEndeligOppgjør.FORELØPIG, null));
    }

    @Test
    public void erOpptalt_BareVTSForeløpig_ErIkkeOpptaltFordiVTSiKunFHSKrets() throws Exception {
        Stemmekrets stemmekrets = stemmekretsOppsettOpptaltstatus(OpptaltStatus.BARE_VTS_FORELØPIG);
        stemmekrets.setOpptaltStatusMax(OpptaltStatus.BARE_FHS_ENDELIG.getStatus());
        Assert.assertEquals(false, stemmekrets.erOpptalt(ForeløpigEndeligOppgjør.FORELØPIG, ValgtingForhand.V));
    }

    @Test
    public void erOpptalt_AlleForeløpig_ErIkkeOpptaltTilEndeligAlle() throws Exception {
        Assert.assertEquals(false, stemmekretsOppsettOpptaltstatus(OpptaltStatus.ALLE_FORELØPIG).erOpptalt(ForeløpigEndeligOppgjør.ENDELIG, null));
    }

    @Test
    public void erOpptalt_BareForeløpigForhånd_ErIkkeOpptaltTilEndeligForhånd() throws Exception {
        Assert.assertEquals(false, stemmekretsOppsettOpptaltstatus(OpptaltStatus.BARE_FHS_FORELØPIG).erOpptalt(ForeløpigEndeligOppgjør.ENDELIG, ValgtingForhand.F));
    }

    @Test
    public void erOpptalt_BareForeløpigForhånd_ErIkkeOpptaltTilEndeligValgting() throws Exception {
        Assert.assertEquals(false, stemmekretsOppsettOpptaltstatus(OpptaltStatus.BARE_FHS_FORELØPIG).erOpptalt(ForeløpigEndeligOppgjør.ENDELIG, ValgtingForhand.V));
    }

    @Test
    public void erOpptalt_BareEndeligForhånd_ErOpptaltTilAlleEndeligFordiMaxErBareEndeligForhånd() throws Exception {
        Stemmekrets stemmekrets = stemmekretsOppsettOpptaltstatus(OpptaltStatus.BARE_FHS_ENDELIG);
        stemmekrets.setOpptaltStatusMax(OpptaltStatus.BARE_FHS_ENDELIG.getStatus());
        Assert.assertEquals(true, stemmekrets.erOpptalt(ForeløpigEndeligOppgjør.ENDELIG, ValgtingForhand.F));
    }

    @Test
    public void erOpptalt_Oppgjør_ErOpptaltTilOppgjør() throws Exception {
        Assert.assertEquals(true, stemmekretsOppsettOpptaltstatus(OpptaltStatus.OPPGJØR).erOpptalt(ForeløpigEndeligOppgjør.OPPGJØR, null));
    }


    private Stemmekrets stemmekretsOppsettOpptaltstatus(OpptaltStatus os) {
        Stemmekrets stemmekrets = new Stemmekrets();
        stemmekrets.setOpptaltStatus(os.getStatus());
        stemmekrets.setOpptaltStatusMax(OpptaltStatus.ALLE_ENDELIG.getStatus());
        return stemmekrets;
    }

    @Test
    public void getStemmer_DetteForeløpigForhånd_200() throws Exception {
        Assert.assertEquals(200, gdm.getOsloStemmekrets("0101").getStemmer(Valg.DETTE, ForeløpigEndeligOppgjør.FORELØPIG, ValgtingForhand.F));
    }

    @Test
    public void getStemmer_DetteEndeligForhånd_200() throws Exception {
        Assert.assertEquals(200, gdm.getOsloStemmekrets("0101").getStemmer(Valg.DETTE, ForeløpigEndeligOppgjør.ENDELIG, ValgtingForhand.F));
    }

    @Test
    public void getStemmer_DetteForeløpigValgting_400() throws Exception {
        Assert.assertEquals(400, gdm.getOsloStemmekrets("0101").getStemmer(Valg.DETTE, ForeløpigEndeligOppgjør.FORELØPIG, ValgtingForhand.V));
    }

    @Test
    public void getStemmer_DetteEndeligValgting_400() throws Exception {
        Assert.assertEquals(400, gdm.getOsloStemmekrets("0101").getStemmer(Valg.DETTE, ForeløpigEndeligOppgjør.ENDELIG, ValgtingForhand.V));
    }

    @Test
    public void getStemmer_DetteEndeligAlle_600() throws Exception {
        Assert.assertEquals(600, gdm.getOsloStemmekrets("0101").getStemmer(Valg.DETTE, ForeløpigEndeligOppgjør.ENDELIG, null));
    }

    @Test
    public void getStemmer_DetteOppgjørAlle_0() throws Exception {
        Assert.assertEquals(0, gdm.getOsloStemmekrets("0101").getStemmer(Valg.DETTE, ForeløpigEndeligOppgjør.OPPGJØR, null));
    }

    @Test
    public void getStemmer_DetteOppgjørAlle_600() throws Exception {
        Stemmekrets stemmekrets = gdm.getOsloStemmekrets("0101");
        // med dette sier vi at stemmetallene har framkommet i oppgjøret
        stemmekrets.setOpptaltStatus(OpptaltStatus.OPPGJØR.getStatus());
        Assert.assertEquals(600, stemmekrets.getStemmer(Valg.DETTE, ForeløpigEndeligOppgjør.OPPGJØR, null));
        // Rydder opp etter testen - vi skal egentlig ikke endre på datamodellen i disse testene
        stemmekrets.setOpptaltStatus(OpptaltStatus.ALLE_ENDELIG.getStatus());
    }

    @Test
    public void getStemmer_SisteAlleAlle_600() throws Exception {
        Assert.assertEquals(600, gdm.getOsloStemmekrets("0101").getStemmer(Valg.SISTE, null, null));
    }
}
