#ifndef GRILLE_H
#define GRILLE_H


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

class Grid
{
	Case tab[9][9];
	unsigned hProb_i, hProb_j;
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)
	{
		int value = *(tab[i][j].possible.begin());
		if (value < 0 || value > 9)
		{
			value = 9;
			ret = false;
		}
		else
			ret = true;
		return value;
	}

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

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

public:

	Grid()  {}
	~Grid() {}

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

	void load(const std::string&);
	void load(int tab[9][9]);
	
	inline Case value(const int i, const int j) const {
		return tab[i][j];
	}

	// 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();


	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].val != g1.tab[i][j].val)
				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
