#ifndef GRILLE_H
#define GRILLE_H


#include <iostream>
#include "Case.h"

class Grid
{
	Case tab[9][9];
	unsigned hProb_i, hProb_j;
	bool     prob_ckecked;

protected:
	void actualize(unsigned i, unsigned j);

	bool line_ok (unsigned j) const;
	bool col_ok  (unsigned i) const;
	bool block_ok(unsigned i, unsigned j) const;

	int toInt(char c);

	inline int getFirstValue(unsigned i, unsigned j, bool& ret) const
	{
		if (i < 0 || i > 9) { ret = false; return 0; }
		if (j < 0 || j > 9) { ret = false; return 0; }

		if (tab[i][j].possible.size() > 1)
		{
			int value = (tab[i][j].proba.top().val);
			if (value < 0 || value > 9)
			{
				value = 0;
				ret = false;
			}
			else
				ret = true;
			return value;
		}
		else
			ret = false;
		return 0;
	}

	inline bool moreChoice() const
	{
		return tab[hProb_i][hProb_j].possible.size() == 0;
	}

	bool impossible(int value, unsigned ii, unsigned jj);

public:

	Grid()  : prob_ckecked(false) {}
	~Grid() {}

	Grid(const Grid&);
	Grid(const std::string&);
	Grid& operator=(const Grid&);

	void load(const std::string&);
	void load(int tab[9][9]);
	
	// function
	void simplify();
	bool final() const; // somme {ligne/col/bloc} == 45
	bool once();        // return false if no changement
	bool best();

	void setProbability();

	inline bool full() const {
		register unsigned i=0, j=0;
		for(;j<9;++j)
			for (i=0;i<9;++i)
				if (tab[i][j].val == 0)
					return false;
		return true;
	}

	bool deprecated();
	
	inline void remove_best() {
		setProbability();
	}


	friend std::ostream& operator<<(std::ostream& out, const Grid& g);
	friend void print(std::ostream& out, const Grid& g);
	
	friend inline bool operator!=(const Grid& g1, const Grid& g2);
	friend inline bool operator==(const Grid& g1, const Grid& g2);
	friend void              save(const Grid& g,  const std::string& s);

};

inline bool operator!=(const Grid& g1, const Grid& g2)
{
	register unsigned i,j;
	for (j=0;j<9;++j)
		for (i=0;i<9;++i)
		{
			if (g2.tab[i][j] != g1.tab[i][j])
				return true;
		}
	return false;
}

inline bool operator==(const Grid& g1, const Grid& g2) {
	return not (g1 != g2);
}



std::ostream& operator<<(std::ostream& out, const Grid& g);
void print(std::ostream& out, const Grid& g);
void save(const Grid& g, const std::string& s);


#endif
