import java.util.*;

public abstract class GameModel
{
    public static int INVALID = -1;
    protected static int DEFAULT_RANGE = 5;
    
    protected int myRows;
    protected int myCols;
    protected GridPoint[][] myGrid;
    protected IGameView myView;
    protected int myRange;
    protected ArrayList myList;
    protected GridPoint[] myArray;
    protected int  myScore;

    public GameModel(int rows, int cols, boolean paired)
    {
	this(rows,cols,DEFAULT_RANGE,paired);
    }

    public GameModel(int rows, int cols)
    {
	this(rows,cols,false);
    }
    
    public GameModel(int rows, int cols, int range)
    {
        this(rows,cols,range, false);
    }
    
    public GameModel(int rows, int cols, int range, boolean paired)
    {
        myRows = rows;
        myCols = cols;
        myRange = range;
        myGrid = new GridPoint[rows][cols];
        myList = new ArrayList();
        myArray = new GridPoint[0];
        initialize(paired);
    }

    public void initialize()
    {
	initialize(false);
    }
    
    public void initialize(boolean paired)
    {
        java.util.Random rando = new java.util.Random();
	clear();
	
	int total = getRows()*getCols();
	int incr = 1;
	if (paired){
	    incr++;
	}
	for(int k=0; k < total; k += incr){
	    int val = rando.nextInt(myRange);
	    myList.add(new Integer(val));
	    if (paired){
		myList.add(new Integer(val));
	    }
	}
	Collections.shuffle(myList);

	int count = 0;
        for(int j=0; j < myRows; j++) {
            for(int k=0; k < myCols; k++) {
                myGrid[j][k] = new GridPoint(0,j,k);
		myGrid[j][k].setValue(((Integer)myList.get(count)).intValue());
		count++;
            }
        }
	clear();
	myScore = 0;	
	showGrid();
	setScore();
    }

    protected boolean inBounds(int row, int col)
    {
        return 0 <= row && row < getRows() && 0 <= col && col < getCols();
    }

    public int getRows()
    {
        return myRows;
    }

    public int getCols()
    {
        return myCols;
    }

    public abstract boolean tryMove(Move move);
    
    public abstract boolean makeMove(Move move);

    protected void showMessage(String message)
    {
	myView.showMessage(message);
    }

    protected void clear()
    {
	myList.clear();
	myArray = new GridPoint[0];
    }

    public void addView(IGameView view)
    {
        myView = view;
	showGrid();
	setScore();
    }

    public void highlight(boolean value)
    {
	if (myView != null){
	    myView.highlight(myArray,value);	    
	}
    }

    public void showGrid()
    {
	if (myView != null){
	    myView.showGrid(myGrid); 
	}
    }

    public void setScore()
    {
	if (myView != null){
	    myView.setScore(myScore); 
	}
    }
}
