#include <stdio.h>
#include <stdlib.h>
#include <graph.h>
#include <time.h>

void affiche_grille(int grille[8][8], int nb_de_lignes, int nb_de_colonnes) {
	int i, j;

	for (i = 0; i < nb_de_lignes; i++) {
		for (j = 0; j < nb_de_colonnes; j++) {		
			printf("%d  ", grille[i][j]);
		}
		putchar('\n');
	}
}

int verifie_si_taquin_complet(int grille[8][8], int nb_de_lignes, int nb_de_colonnes) {
	int compteur = 0;
	int i, j;

	for (i = 0; i < nb_de_lignes; i++) {
		for (j = 0; j < nb_de_colonnes; j++) {
			if (grille[i][j] != compteur) {
				return 0; /* Pas complet */
			}
			compteur++;
		}
	} 

	return 1; /* Complet */
}

int peut_decaler_en_haut(int grille[8][8], int nb_de_lignes, int nb_de_colonnes) {
	int i;

	for (i = 0; i != nb_de_lignes; i++) {
		if (grille[nb_de_colonnes-1][i] == 0) {
			return 0;
		}
	} 

	return 1;
}

int peut_decaler_en_bas(int grille[8][8], int nb_de_lignes, int nb_de_colonnes) {
	int i;

	for (i = 0; i != nb_de_lignes; i++) {
		if (grille[0][i] == 0) {
			return 0;
		}
	}

	return 1;
}


int peut_decaler_a_gauche(int grille[8][8], int nb_de_lignes, int nb_de_colonnes) {
	int i;

	for (i = 0; i != nb_de_colonnes; i++) {
		if (grille[i][nb_de_lignes-1] == 0) {
			return 0;
		}
	}

	return 1;
}


int peut_decaler_a_droite(int grille[8][8], int nb_de_lignes, int nb_de_colonnes) {
	int i;

	for (i = 0; i != nb_de_colonnes; i++) {
		if (grille[i][0] == 0) {
			return 0;
		}
	}

	return 1;
} 


void mettre_a_jour_grille(int tab_image[8][8], int nb_de_lignes, int nb_de_colonnes, int decalage, int indice_case_vide_x, int indice_case_vide_y, int direction_decalage, int largeur_image, int hauteur_image) {
	int pos_img_x;
	int pos_img_y;
	int pos_x;
	int pos_y;

	switch (direction_decalage) {
		case 1: /* haut */
			pos_img_x = (tab_image[indice_case_vide_x][indice_case_vide_y] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x][indice_case_vide_y] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = indice_case_vide_y * (largeur_image / nb_de_colonnes);
		    pos_y = indice_case_vide_x * (hauteur_image / nb_de_lignes);

		    ChoisirCouleurDessin(CouleurParNom("white"));

			RemplirRectangle(
				pos_x + decalage*(indice_case_vide_y+1), pos_y + decalage*(indice_case_vide_x+1), largeur_image / nb_de_colonnes, hauteur_image / nb_de_lignes 
			);

        	pos_img_x = (tab_image[indice_case_vide_x-1][indice_case_vide_y] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x-1][indice_case_vide_y] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = (indice_case_vide_y) * (largeur_image / nb_de_colonnes);
	        pos_y = (indice_case_vide_x-1) * (hauteur_image / nb_de_lignes);

        	ChargerImage("./img/p4.img", 
	            pos_x + decalage * indice_case_vide_y + 10, pos_y + decalage * (indice_case_vide_x-1) + 10, 
	            pos_img_x, pos_img_y, 
	            largeur_image / nb_de_colonnes, 
	            hauteur_image / nb_de_lignes
        	);

			break;

		case 2: /* bas */
			pos_img_x = (tab_image[indice_case_vide_x][indice_case_vide_y] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x][indice_case_vide_y] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = indice_case_vide_y * (largeur_image / nb_de_colonnes);
		    pos_y = indice_case_vide_x * (hauteur_image / nb_de_lignes);

		    ChoisirCouleurDessin(CouleurParNom("white"));

			RemplirRectangle(
				pos_x + decalage*(indice_case_vide_y+1), pos_y + decalage*(indice_case_vide_x+1), largeur_image / nb_de_colonnes, hauteur_image / nb_de_lignes 
			);

			pos_img_x = (tab_image[indice_case_vide_x+1][indice_case_vide_y] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x+1][indice_case_vide_y] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = (indice_case_vide_y) * (largeur_image / nb_de_colonnes);
	        pos_y = (indice_case_vide_x+1) * (hauteur_image / nb_de_lignes);

        	ChargerImage("./img/p4.img", 
	            pos_x + decalage * indice_case_vide_y + 10, pos_y + decalage * (indice_case_vide_x+1) + 10, 
	            pos_img_x, pos_img_y, 
	            largeur_image / nb_de_colonnes, 
	            hauteur_image / nb_de_lignes
        	);
        	break;

        case 3: /* gauche */

        	printf("Coord case vide : %d | %d", indice_case_vide_x, indice_case_vide_y);
        	pos_img_x = (tab_image[indice_case_vide_x][indice_case_vide_y] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x][indice_case_vide_y] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = indice_case_vide_y * (largeur_image / nb_de_colonnes);
		    pos_y = indice_case_vide_x * (hauteur_image / nb_de_lignes);

		    ChoisirCouleurDessin(CouleurParNom("white"));

			RemplirRectangle(
				pos_x + decalage*(indice_case_vide_y+1), pos_y + decalage*(indice_case_vide_x+1), largeur_image / nb_de_colonnes, hauteur_image / nb_de_lignes 
			);

        	pos_img_x = (tab_image[indice_case_vide_x][indice_case_vide_y-1] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x][indice_case_vide_y-1] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = (indice_case_vide_y-1) * (largeur_image / nb_de_colonnes);
	        pos_y = (indice_case_vide_x) * (hauteur_image / nb_de_lignes);

        	ChargerImage("./img/p4.img", 
	            pos_x + decalage * (indice_case_vide_y-1) + 10, pos_y + decalage * (indice_case_vide_x) + 10, 
	            pos_img_x, pos_img_y, 
	            largeur_image / nb_de_colonnes, 
	            hauteur_image / nb_de_lignes
        	);
        	break;

        case 4: /* droite */
        	pos_img_x = (tab_image[indice_case_vide_x][indice_case_vide_y] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x][indice_case_vide_y] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = indice_case_vide_y * (largeur_image / nb_de_colonnes);
		    pos_y = indice_case_vide_x * (hauteur_image / nb_de_lignes);

		    ChoisirCouleurDessin(CouleurParNom("white"));

			RemplirRectangle(
				pos_x + decalage*(indice_case_vide_y+1), pos_y + decalage*(indice_case_vide_x+1), largeur_image / nb_de_colonnes, hauteur_image / nb_de_lignes 
			);

        	pos_img_x = (tab_image[indice_case_vide_x][indice_case_vide_y+1] % nb_de_colonnes) * largeur_image / nb_de_colonnes;
			pos_img_y = tab_image[indice_case_vide_x][indice_case_vide_y+1] / nb_de_colonnes * hauteur_image / nb_de_lignes;
			pos_x = (indice_case_vide_y+1) * (largeur_image / nb_de_colonnes);
	        pos_y = (indice_case_vide_x) * (hauteur_image / nb_de_lignes);

        	ChargerImage("./img/p4.img", 
	            pos_x + decalage * (indice_case_vide_y+1) + 10, pos_y + decalage * (indice_case_vide_x) + 10, 
	            pos_img_x, pos_img_y, 
	            largeur_image / nb_de_colonnes, 
	            hauteur_image / nb_de_lignes
        	);
        	break;

	}
}


int main(void) {
	int nb_de_lignes = 5;
	int nb_de_colonnes = 5;
	int decalage = 10;
	int largeur_image = 1710;
	int hauteur_image = 900;
	int tab_image[8][8];
	int i;
	int j;
	int compteur = 0;
	int indice_case_vide_x = 0;
	int indice_case_vide_y = 0; 

	srand(time(NULL));

	for (i = 0; i != nb_de_lignes; i++) {
		for (j = 0; j != nb_de_colonnes; j++) {
			tab_image[i][j] = compteur;
			compteur++;
		}
	}

	int rand_1_1 = (rand() % nb_de_lignes);
	int rand_1_2 = (rand() % nb_de_colonnes);

	int rand_2_1 = (rand() % nb_de_lignes);
	int rand_2_2 = (rand() % nb_de_colonnes);

	compteur = 0;

	while (compteur < 100) {
		while (rand_1_1 + rand_1_2 == 0) {
			rand_1_1 = (rand() % nb_de_lignes);
			rand_1_2 = (rand() % nb_de_colonnes);
		}

		while (rand_2_1 + rand_2_2 == 0) {
			rand_2_1 = (rand() % nb_de_lignes);
			rand_2_2 = (rand() % nb_de_colonnes);
		}

		int temp = tab_image[rand_1_1][rand_1_2];
		tab_image[rand_1_1][rand_1_2] = tab_image[rand_2_1][rand_2_2];
		tab_image[rand_2_1][rand_2_2] = temp;

		rand_1_1 = (rand() % nb_de_lignes);
		rand_1_2 = (rand() % nb_de_colonnes);

		rand_2_1 = (rand() % nb_de_lignes);
		rand_2_2 = (rand() % nb_de_colonnes);

		compteur++;
	}


    affiche_grille(tab_image, nb_de_lignes, nb_de_colonnes);


	InitialiserGraphique();
	CreerFenetre(10, 10, largeur_image + decalage * (nb_de_lignes+1), hauteur_image + decalage * (nb_de_colonnes+1));
	
	for (i = 0; i < nb_de_lignes; i++) {
    	for (j = 0; j < nb_de_colonnes; j++) {
    		if (j == 0 && i == 0){ 
    			j++;
    		}
			int pos_img_x = (tab_image[i][j] % nb_de_colonnes) * (largeur_image / nb_de_colonnes);
	        int pos_img_y = (tab_image[i][j] / nb_de_colonnes) * (hauteur_image / nb_de_lignes);
	        int pos_x = j * (largeur_image / nb_de_colonnes);
	        int pos_y = i * (hauteur_image / nb_de_lignes);


	        ChargerImage("./img/p4.img", 
	            pos_x + decalage * j + 10, pos_y + decalage * i + 10, 
	            pos_img_x, pos_img_y, 
	            largeur_image / nb_de_colonnes, 
	            hauteur_image / nb_de_lignes
        	);
        
	    }
    }

    while (!verifie_si_taquin_complet(tab_image, nb_de_lignes, nb_de_colonnes)) {
    	if (ToucheEnAttente()) {
    		int touche = Touche();

    		if (touche == XK_Up && peut_decaler_en_haut(tab_image, nb_de_lignes, nb_de_colonnes)) {
    			int temp = tab_image[indice_case_vide_x+1][indice_case_vide_y];
    			tab_image[indice_case_vide_x+1][indice_case_vide_y] = 0;
    			tab_image[indice_case_vide_x][indice_case_vide_y] = temp;

    			indice_case_vide_x++;

    			mettre_a_jour_grille(tab_image, nb_de_lignes, nb_de_colonnes, decalage, indice_case_vide_x, indice_case_vide_y, 1, largeur_image, hauteur_image);
    		} else if (touche == XK_Down && peut_decaler_en_bas(tab_image, nb_de_lignes, nb_de_colonnes)) {
    			int temp = tab_image[indice_case_vide_x-1][indice_case_vide_y];
    			tab_image[indice_case_vide_x-1][indice_case_vide_y] = 0;
    			tab_image[indice_case_vide_x][indice_case_vide_y] = temp;

    			indice_case_vide_x--;

    			mettre_a_jour_grille(tab_image, nb_de_lignes, nb_de_colonnes, decalage, indice_case_vide_x, indice_case_vide_y, 2, largeur_image, hauteur_image);
    		} else if (touche == XK_Left && peut_decaler_a_gauche(tab_image, nb_de_lignes, nb_de_colonnes)) {
    			int temp = tab_image[indice_case_vide_x][indice_case_vide_y+1];
    			tab_image[indice_case_vide_x][indice_case_vide_y+1] = 0;
    			tab_image[indice_case_vide_x][indice_case_vide_y] = temp;

    			indice_case_vide_y++;

    			mettre_a_jour_grille(tab_image, nb_de_lignes, nb_de_colonnes, decalage, indice_case_vide_x, indice_case_vide_y, 3, largeur_image, hauteur_image);
    		} else if (touche == XK_Right && peut_decaler_a_droite(tab_image, nb_de_lignes, nb_de_colonnes)) {
    			int temp = tab_image[indice_case_vide_x][indice_case_vide_y-1];
    			tab_image[indice_case_vide_x][indice_case_vide_y-1] = 0;
    			tab_image[indice_case_vide_x][indice_case_vide_y] = temp;

    			indice_case_vide_y--;

    			mettre_a_jour_grille(tab_image, nb_de_lignes, nb_de_colonnes, decalage, indice_case_vide_x, indice_case_vide_y, 4, largeur_image, hauteur_image);
    		
    		}

    		affiche_grille(tab_image, nb_de_lignes, nb_de_colonnes);
    	}
    }

    ChoisirCouleurDessin(CouleurParNom("white"));
    RemplirRectangle(0, 0, hauteur_image, largeur_image);

    ChargerImage("./img/p4.img",
    	20, 20,
    	0, 0,
    	largeur_image, hauteur_image
    );

    Touche();
	FermerGraphique();
	return EXIT_SUCCESS;
}


