/*
  crossword -- a crossword game
  Copyright (C) 2000 Falk Hueffner

  This program is free software; you can redistribute it and/or modify it
  under the terms of the GNU General Public License as published by the Free
  Software Foundation; either version 2 of the License, or (at your option)
  any later version.
  
  This program is distributed in the hope that it will be useful, but WITHOUT
  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
  more details.
  
  You should have received a copy of the GNU General Public License along with
  this program; if not, write to the Free Software Foundation, Inc., 59 Temple
  Place, Suite 330, Boston, MA 02111-1307 USA

  $Id: Rack.hh,v 1.7 2000/11/28 18:30:23 falk Exp $
*/

#ifndef RACK_HH
#define RACK_HH

#include <algorithm>
#include <assert.h>
#include <iostream>
#include <vector>

#include "Tile.hh"

class Rack {
    friend ostream& operator<<(ostream& out, const Rack& rack);
public:
    typedef int Handle;

    Rack() { }

    void set(const string& s) {
	_numTiles = s.length();
	_tiles.resize(_numTiles);
	_onRack.resize(_numTiles);
	for (int i = 0; i < _numTiles; ++i) {
	    _tiles[i] = s[i];
	    _onRack[i] = true;
	}
	sort(_tiles.begin(), _tiles.end());
	_lastBlank = 0;
    }

    Handle begin() const { return next(-1); }
    static Handle end() { return -1; }
    bool empty() const { return begin() == end(); }

    Tile get(Handle i) const { return _tiles[i]; }
    void draw(Handle i) { _onRack[i] = false; }
    void putBack(Handle i) { _onRack[i] = true; }

    int next(Handle last) const {
	for (int i = last + 1; i < _numTiles; ++i)
	    if (_onRack[i])
		return i;

	return end();
    }

    // To avoid duplicate results where just two blanks are swapped, we
    // request each blank represents a higher tile than the previous. The
    // value of the
    Tile lastBlank() const { return _lastBlank; }
    void setLastBlank(Tile t) { _lastBlank = t; }

private:
    // don't copy Racks
    Rack(const Rack& other); // FIXME also assignment

    int _numTiles;
    Tile _lastBlank;
    vector<Tile> _tiles;
    vector<bool> _onRack;
};

inline ostream& operator<<(ostream& out, const Rack& rack) {
    out << '{';
    for (unsigned int i = 0; i < Rules::maxRackTiles(); ++i)
	if (rack._onRack[i])
	    out << rack._tiles[i];
    return out << '}';
}

#endif

