package no.valg.valgnatt.database;

import java.math.BigDecimal;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.HashSet;
import java.util.Set;
import java.util.TreeSet;

public class Konstanter {

    // Konstanter relatert til Andre/Andre2-partivisning
    public static final String ANDRE = "Andre";
    public static final String ANDRE2 = "Andre2";
    public static final String PARTIKATEGORIANDRE = "0";

    public static final String BLANKE = "BLANKE";

    /* Vi setter default frammøte til 70% (litt for lavt for ST-valg, litt for høyt for KO-valg, altfor høyt for FY-valg). */
    public static final float DEFAULT_FRAMMØTE_PROSENT = 0.7f;
    public static final float OSPROSENT_ALLE_FORELØPIGE_STEMMER_OPPTALT = 0.998f;
    public static final float OSPROSENT_ALLE_ENDELIGE_STEMMER_OPPTALT = 0.999f;
    public static final float OSPROSENT_ALLE_OPPGJØR_FERDIG = 1f;


    /* Vi setter default-verdi til 20% for andel FHS av totalt antall stemmer - benyttes i opptaltstatus-indikatorene */
    public static final float DEFAULT_FHS_ANDEL = 0.2f;

    // Det finnes egentlig ikke et valgdistrikt for hele landet, men utjevningsmandatene knyttes enklest til landsnivå grunnet
    // måten man regner det ut på. I tillegg er det behov for å lagre prognoser og resultater på landsnivå. Dermed
    public static final String VALGDISTRIKT_NORGE = "00";

    // Alle kommuner har minst en krets, og det er 0000-kretsen. Denne kretsen mottar også alltid alle FHS. Øvrige kretser
    // mottar kun VTS. 0000-kretsen vil også kunne motta VTS, men i kretsfordelte kommuner vil dette typisk være fremmedstemmer o.l.
    public static final String DEFAULT_KRETS = "0000";

    public static final String DEFAULT_PARTIKATEGORI = "3"; // Er et lokalt parti
    public static final String DEFAULT_VISNINGSSEKVENS = "99999"; // Blir sortert sist

    public static final String PARTI_TOTAL = "!TOTAL!"; // Partikode som reserveres til å summere opp total-tall på et geografisk område

    // Før 2005 hadde man 8 utjevningsmandater på 19 fylker. Dette kunne ikke systemet håndtert.
    // Bare et helt antall utjevningsmandater pr fylke fungerer.
    public static final int UTJEVNINGSMANDATER_PR_FYLKE = 1;
    public static final String OSLO_FNR = "03";
    public static final String OSLO_KNR = "0301";
    public static final String STAVANGER_KNR = "1103";
    public static final String BERGEN_KNR = "1201";
    public static final String TRONDHEIM_KNR = "1601";

    // Maks presisjon i alle BigDecimal divisjoner
    public static final int MAKS_PRESISJON = 20;

    // MSI des 2016: Konstanten brukes i matriseberegningen og har vært 0.05 siden 2003. Ved å sette konstanten nærmere
    // 0 så trekkes betakoffesientene mer mot aprioriverdiene.
    public static final double TAU = 0.05;

    // Prognoser kan fint beregnes selv med bare én krets i sample. Imidlertid blir denne beregningen da dårligere sett
    // i forhold til å benytte opptalte stemmer, fordi vi har mye FHS i opptalte stemmer. Basert på mange tester/simuleringer
    // setter vi derfor grensen til 4 kretser fullt opptalt og minimum 1000*(ant-kretser) stemmer. Dette fører til at landsprognosen gjerne
    // første gang kan beregnes rundt kl 2015, mens fylkesprognoser kan komme fra kl 21 og utover, avhengig av opptellingstempo
    // til kommuner i dette fylket.
    public static final int MIN_KRETSER = 4;
    public static final int STRATA_MIN_KRETSER = 25;
    public static final BigDecimal SPERREGRENSE = new BigDecimal("0.04");

    // MSI des 2016: Listestemmer kom kretsvis i 2011, men skal fra 2015 kun komme i default-krets. Det ble gjort feil i 2015-valget, slik at
    // listestemmene likevel kom i alle kretsene, men da med det samme antall som for default-kretsen. Denne feilen var strengt tatt ikke problematisk
    // for systemet, fordi det innbyrdes forholdet mellom listestemmene var fortsatt det samme, og dermed ville man få den samme
    // mandatfordeling. Imidlertid ble summene av listestemmer i storbyene så store at man måtte begynt å benytte long-primitiv, noe jeg syntes
    // ble stygt. Jeg kunne alternativt ha gått igjennom alle stemmeskjema fra 2015 og fjernet listestemmer fra alle kretsene (bortsett fra default-
    // kretsen), men inntil videre håndtere jeg dette ved å ikke lese dem inn.
    public static final int LISTESTEMMER_SUMMERT_I_DEFAULT_KRETS_ÅR = 2015;
    public static final double DEFAULT_APRIORI_BK_FHS = 0.7;
    public static final double DEFAULT_APRIORI_BK_HS1 = 0.2;
    public static final double DEFAULT_APRIORI_BK_HS2 = 0.1;

    // prognoser for andre større kommuner (med mange kretser) på sikt (etter 2017?). Hvorvidt dette gir noe særlig
    // avhenger av hvor gode prognosene egentlig er. Slik det ligger an nå (jul 2016) har jeg lite tro på at det
    // er noe vits.
    private static final Set<String> PROGNOSEKOMMUNER = new TreeSet<>(Arrays.asList(OSLO_KNR, STAVANGER_KNR, BERGEN_KNR, TRONDHEIM_KNR));
    private static final Set<String> STORBYER = new TreeSet<>(Arrays.asList(OSLO_KNR, STAVANGER_KNR, BERGEN_KNR, TRONDHEIM_KNR));

    // Kataloger for runtime-konfigurasjon
    // tmp brukes som standardverdi i System.getProperty fordi jboss.server.data.dir ikke er satt når enhetstester kjøres
    public static final Path WILDFLY_DATAKATALOG = Paths.get(System.getProperty("jboss.server.data.dir", "/tmp"));
    public static final Path AUTOOPPSETT_ROTKATALOG = Paths.get(WILDFLY_DATAKATALOG.toString(), "runtimeconfig");
    public static final Path AUTOOPPSETT_GRUNNLAGSDATAKATALOG = Paths.get(AUTOOPPSETT_ROTKATALOG.toString(), "grunnlagsdata");
    public static final Path AUTOOPPSETT_INITIALDATAKATALOG = Paths.get(AUTOOPPSETT_ROTKATALOG.toString(), "initialdata");
    public static final String AUTOOPPSETT_INITIALDATA = "autooppsett";

    // Noen kommuner vil ikke ha noen stemmer. Dette er tilfelle for opptellingskommunen i valgdistrikter som ikke har kommuner hvor det ikke foregår opptelling. 
    // Dvs opptellingskommunen i valgdistrikt med kun 30+ kommuner i sametinget.
    private static final String AVJOVARI = "0002";
    private static final String NORDRE = "0003";
    private static final Set<String> KOMMUNER_UTEN_STEMMER = new HashSet<>(Arrays.asList(AVJOVARI, NORDRE));

    private Konstanter() {
        //Hide default contructor
    }

    public static Set<String> getPrognosekommuner() {
        return PROGNOSEKOMMUNER;
    }

    public static boolean erPrognosekommune(String kommnr) {
        return PROGNOSEKOMMUNER.contains(kommnr);
    }

    public static boolean isStorby(String kommnr) {
        return STORBYER.contains(kommnr);
    }
    
    public static boolean erKommuneUtenStemmer(String kretsnummer) {
        return KOMMUNER_UTEN_STEMMER.contains(kretsnummer);
    }

}
