// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: ffset.h 58 2008-01-11 15:15:59Z sebastian $
//
////////////////////////////////////////////////////////////////////

#ifndef FF_SET_H
#define FF_SET_H

#include "ff_heuristic/ffarray.h"
#include <vector>
#include <cassert>

namespace ff {
    
    ////////////////////////////////////////////////////////////////////
    //
    // A PtrSet is a fixed size set of pointers. Added elements become
    // members after incLevel() is called
    //
    ////////////////////////////////////////////////////////////////////

    template<class T> class PtrSet {
    private:
	size_t capacity;
	PtrArray<T> current, next;	
	std::vector<bool> members;

    public:
	typedef typename PtrArray<T>::iterator iterator;
	typedef typename PtrArray<T>::const_iterator const_iterator;
	
	PtrSet(size_t capacity) : 
	    capacity(capacity),
	    current(capacity), 
	    next(capacity),
	    members(capacity, false)
	    {}
	
	PtrSet(const PtrSet& pset) : 
	    capacity(pset.capacity), 
	    current(pset.current), 
	    next(pset.next), 
	    members(pset.members) 
	    {}

	bool isMember(const T* element) const {
	    return members[element->getID()];
	}
	
	bool add(T* element) {
	    if (isMember(element)) {
		return false;
	    } else {
		next.add(element);
		members[element->getID()] = true;
		return true;
	    }
	}

	void incLevel() {
	    // current = next
	    // next = {}
	    current.swap(next);
	    next.clear();
	}

	void clear() {
	    current.clear();
	    next.clear();
	    members.assign(capacity, false);
	}

	size_t size() const {
	    return current.size();
	}

	bool empty() const {
	    return current.empty();
	}

	iterator begin() {
	    return current.begin();
	}

	const_iterator begin() const {
	    return current.begin();
	}

	iterator end() {
	    return current.end();
	}

	const_iterator end() const {
	    return current.end();
	}	

	void swap(PtrSet& other) {
	    next.swap(other.next);
	    current.swap(other.current);
	    members.swap(other.members);
	    swap(capacity, other.capacity);
	}
    };    
}

#endif /* FF_SET_H */
