package fanch.multijeu.findwords.data;

import fanch.multijeu.findwords.data.checker.WordChecker;
import fanch.multijeu.common.utils.DoubleUtils;
import fanch.multijeu.common.utils.IntUtils;
import fanch.multijeu.common.utils.LetterUtils;

public class LetterGenerator {



    public static char randEquiChar(boolean accent)
    {
        int tab[][] = (accent?LetterUtils.LETTER_FREQ:LetterUtils.LETTER_ASCII_FREQ);
        return (char)tab[IntUtils.rand(0, tab.length-1)][0];
    }

    public static char randEquiV(boolean accent)
    {
        int tab[][] = (accent?LetterUtils.LETTER_FREQ:LetterUtils.LETTER_ASCII_FREQ);
        int count = (accent?LetterUtils.LETTER_FREQ_V:LetterUtils.LETTER_FREQ_V);
        int nth = IntUtils.rand(1,count);

        for(int i=0; i<tab.length; i++){
            if(tab[i][2]==0) nth--;
            if(nth==0) return (char) tab[i][0];
        }
        return 'a';
    }

    public static char randEquiC(boolean accent)
    {
        int tab[][] = (accent?LetterUtils.LETTER_FREQ:LetterUtils.LETTER_ASCII_FREQ);
        int count = (accent?LetterUtils.LETTER_FREQ_C:LetterUtils.LETTER_FREQ_C);
        int nth = IntUtils.rand(1,count);

        for(int i=0; i<tab.length; i++){
            if(tab[i][2]==0) nth--;
            if(nth==1) return (char) tab[i][0];
        }
        return 'a';
    }



    public enum Strategy {
        PONDERATE,
        EQUIPROBABLE
    }

    public enum CVStrategy {
        CONSTRAINT,
        RAND_RATIO
    }

    public static class Attrs extends WordChecker.Attrs {


        public Strategy strategy=Strategy.PONDERATE;
        public CVStrategy cvstrategy=CVStrategy.CONSTRAINT;

        public boolean useAccent=false;
        public int minLettersCount=3;
        public int maxLettersCount=7;

        //pour CVStrategy=CONSTRAINT
        public int minVoyellesCount=1;
        public int minConsonnesCount=1;
        //fin


        //pour CVStrategy=RAND_RATIO = (NVoy/(NVoy+NCons))
        public double minCVRatio=0.2;
        public double maxCVRatio=0.5;
        //fin



    }

    protected transient StringBuilder mString = new StringBuilder();
    protected int   mVCount=0;
    protected int  mCCount=0;
    protected int  mEndSize=0;

    protected Attrs mAttrs=new Attrs();

    public LetterGenerator() { }
    public LetterGenerator(Attrs a) { mAttrs=a;}

    protected String generatePonderateConstraint()
    {
        while(mCCount+mVCount<mEndSize) {
            if (mCCount + mVCount + 1 == mEndSize &&
                    (mCCount < mAttrs.minConsonnesCount || mVCount < mAttrs.minVoyellesCount)) {
                if (mCCount < mAttrs.minConsonnesCount)
                    append(LetterUtils.randConsonne(mAttrs.useAccent));
                else
                    append(LetterUtils.randVoyelle(mAttrs.useAccent));
            }
            append(LetterUtils.randLetter(mAttrs.useAccent));
        }
        return mString.toString();
    }

    protected String generateEquiprobableConstraint()
    {
        while(mCCount+mVCount<mEndSize) {
            if (mCCount + mVCount + 1 == mEndSize &&
                    (mCCount < mAttrs.minConsonnesCount || mVCount < mAttrs.minVoyellesCount)) {
                if (mCCount < mAttrs.minConsonnesCount)
                    append(randEquiC(mAttrs.useAccent));
                else
                    append(randEquiV(mAttrs.useAccent));
            }
            append(randEquiChar(mAttrs.useAccent));
        }
        return mString.toString();
    }

    protected String generatePonderateRR()
    {
        double ratio = DoubleUtils.rand(mAttrs.maxCVRatio, mAttrs.maxCVRatio);
        int nv = (int)(ratio*mEndSize);
        int nc = mEndSize-nv;

        for(int i=0; i<nc; i++)
            append(LetterUtils.randVoyelle(mAttrs.useAccent));

        for(int i=0; i<nv; i++)
            append(LetterUtils.randConsonne(mAttrs.useAccent));

        return mString.toString();
    }


    protected String generateEquiprobableRR()
    {
        double ratio = DoubleUtils.rand(mAttrs.maxCVRatio, mAttrs.maxCVRatio);
        int nv = (int)(ratio*mEndSize);
        int nc = mEndSize-nv;

        for(int i=0; i<nc; i++)
            append(randEquiV(mAttrs.useAccent));

        for(int i=0; i<nv; i++)
            append(randEquiC(mAttrs.useAccent));

        return mString.toString();
    }

    public String generate()
    {
        mCCount=mVCount=0;
        mString=new StringBuilder();
        mEndSize=IntUtils.rand(mAttrs.minLettersCount, mAttrs.maxLettersCount);


        switch(mAttrs.strategy)
        {
            case PONDERATE:
                switch(mAttrs.cvstrategy){
                    case CONSTRAINT: return generatePonderateConstraint();
                    case RAND_RATIO: return generatePonderateRR();
                }
            case EQUIPROBABLE:
                switch(mAttrs.cvstrategy){
                    case CONSTRAINT: return generatePonderateConstraint();
                    case RAND_RATIO: return generateEquiprobableRR();
                }
            default:
                return null;
        }
    }


    protected void append(char c)
    {
        mString.append(c);
        if(LetterUtils.isVoyelle(c)) mVCount++;
        else mCCount++;
    }


}
