#define DIMENSION 4
#define POCET_PERM_VRCHOLOV 24
#define POCET_VRCHOLOV 36 //POCET_PERM_VRCHOLOV*POCET_FARIEB/2 //36
#define POCET_VRCHOLOV_FARBA 12 //POCET_VRCHOLOV/POCET_FARIEB   //12

#define FAKTORIAL_FARIEB 3*2
#define POCET_BIN_VRCHOLOV 16
#define VELKOST_D 10    //treba doplnit

#define POCET_FARIEB DIMENSION-1
#define POCET_KOOR 4
#define POCET_SUSEDOV 2*(POCET_FARIEB-1)
#define MAX_FARIEB 150000
#define MAX_RIESENI 100000

#define MAXN POCET_VRCHOLOV
#define MAXM ((MAXN+WORDSIZE-1)/WORDSIZE)

#ifndef _VERTEX_STAR_BFS_H
#define	_VERTEX_STAR_BFS_H

#include "./global_functions.h"

class VERTEX_STAR_BFS {
public:
    VERTEX_STAR_BFS(int a,int b, int c, int d, int e, int f, int g, int h);

    virtual ~VERTEX_STAR_BFS();
private:
    int M, vrchol, novy_vrchol, sused, m, pom;
    graph g[MAXN*MAXN], cg[MAXN*MAXN], cgi[MAXN*MAXN];
    nvector lab[MAXN], ptn[MAXN]; //povodne nvector

    int orbits[MAXN];
    set * gv;
    statsblk stats;
    setword workspace[50 * MAXM];

    struct FAKTORIZACIA {
        unsigned int ofarbenie[POCET_VRCHOLOV];
        unsigned int laby[FAKTORIAL_FARIEB][POCET_VRCHOLOV];
        unsigned int D_tabulka[VELKOST_D * POCET_VRCHOLOV / 4];
    };
    unsigned int faktorizacia_pocet;
    typedef struct FAKTORIZACIA item_faktorizacia;
    item_faktorizacia * faktorizacia[MAX_RIESENI];

    struct OPTION {
        unsigned int SEMI_CHECK; //  1 - SEMI    //  2 - PERF    // 0 - NIC
        unsigned int SEMI_POLOHA_POCAS; //  1 - ZAPNUTE    //  0 - VYPNUTE
        unsigned int SEMI_POLOHA_KONIEC; //  1 - ZAPNUTE    //  0 - VYPNUTE
        unsigned int VYPIS; //  1 - zapnuty //  0 - vypnuty
        unsigned int NAUTY; //  1 - zapnuty //  0 - vypnuty
        unsigned int NAUTY_POLOHA_KONIEC; //  1 - na konci kazdej farby   2 - na konci ofarbenia
        unsigned int NAUTY_POLOHA_POCAS;
        unsigned int NAUTY_D_TABULKA;
    } option;

    int perm_pole_2[2][2];
    int perm_pole_2_fak;
    int perm_pole_3[6][3];
    int perm_pole_3_fak;
    int perm_pole_4[24][4];
    int perm_pole_4_fak;
    int perm_pole_5[120][5];
    int perm_pole_5_fak;
    int perm_pole_6[720][6];
    int perm_pole_6_fak;
    int perm_pole_tmp;

    int default_ofarbenie[POCET_VRCHOLOV]; //={0,-1,-1,-1,4,-1,-1,-1,8,-1,-1,-1};
    int su_ofarbene[POCET_VRCHOLOV]; //={1,0,0,0,1,0,0,0,1,0,0,0};
    int ofarbenie[POCET_VRCHOLOV];
    int susedia_napln_def[DIMENSION];
    int cesta_global[2 * POCET_VRCHOLOV_FARBA - 1];
    permutation lab_farby_level[MAX_FARIEB][POCET_VRCHOLOV];
    int lab_farby_level_pocet;
    permutation lab_farby_level_pocas[25][40][500][POCET_VRCHOLOV];
    int lab_farby_level_pocet_pocas[25][40];
    int ofarbenia_bin_vrcholov_global[POCET_BIN_VRCHOLOV][POCET_FARIEB];
    int su_ofarbene_global[POCET_VRCHOLOV];
    int zapis_iba_do_labu;

    int nove_hrany[POCET_PERM_VRCHOLOV][POCET_PERM_VRCHOLOV];
    int hrany[POCET_VRCHOLOV][2];
    int perm_hrany[POCET_VRCHOLOV][DIMENSION * 2]; //hrana a jej permutacne vrcholy
    int perm_vrcholy[POCET_PERM_VRCHOLOV][DIMENSION]; //permutacne cislo vrchola
    int vyskyt_perm_vrcholov[POCET_PERM_VRCHOLOV]; //kvoli hranam
    int perm_susedia[POCET_PERM_VRCHOLOV][DIMENSION - 1]; //pole susedov permutacii, po vymene i-teho prvku
    int ofarbenie_perm_vrcholov_global[POCET_PERM_VRCHOLOV][POCET_FARIEB];

    char binary[DIMENSION];
    int bin_susedia[POCET_BIN_VRCHOLOV][DIMENSION];
    int nove_vrcholy[POCET_BIN_VRCHOLOV][POCET_BIN_VRCHOLOV];
    int default_susedia[POCET_VRCHOLOV][POCET_SUSEDOV];

    void najdi_faktorizaciu(int vrchol_lokal, int ofarbenie_perm_vrcholov[POCET_PERM_VRCHOLOV][POCET_FARIEB], int su_ofarbene_lokal[POCET_VRCHOLOV]);
    void vyrataj_D_tabulku(int akt_faktorizacia);
    int check_level_P1F(unsigned int vrchol, unsigned int p_farba, unsigned int d_farba, int su_ofarbene_lokal[POCET_VRCHOLOV]);
    inline int check_P1F(int su_ofarbene_lokal[POCET_VRCHOLOV], int vrchol);
    int RunNautyKoniec(int su_ofarbene_lokal[POCET_VRCHOLOV]);
    int RunNautyPocas(int su_ofarbene_lokal[POCET_VRCHOLOV], graph g_lokal[MAXN*MAXN], graph cg_lokal[MAXN*MAXN], graph cgi_lokal[MAXN*MAXN], int vrchol);

    void NaplnDefault();
    void visit(int *Value, int N, int k);
    void print(const int *v, const int size);

};

#endif	/* _VERTEX_STAR_BFS_H */

