// -*- mode: C++; c-file-style: "stroustrup"; c-basic-offset: 4; -*-
////////////////////////////////////////////////////////////////////
//
// $Id: ffuheur.h 817 2011-09-10 13:31:09Z Sebastian Kupferschmid $
//
////////////////////////////////////////////////////////////////////

#ifndef USELESS_FF_HEURISTIC_H
#define USELESS_FF_HEURISTIC_H

#include "useless.h"
#include <vector>

class System;
class Edge;

namespace ff {
    class Edge;

    template<class FFHeur> class FFUHeuristic : public Useless {
    private:
    	FFHeur heuristic;
	
    	virtual int32_t evalAbstracted(const State* state, const std::vector<bool>& abstracted) {
    	    heuristic.abstracted = &abstracted;
    	    return heuristic.eval(state);
    	}
    public:
    	FFUHeuristic(const Task* task, const Options* opts) :	
    	    Useless(task, opts),
    	    heuristic(task, opts)
    	    {}
    };

    ////////////////////////////////////////////////////////////////////

    template<class Base> class UselessHelper : public Base {
    public:
    	const vector<bool>* abstracted;

    	UselessHelper(const Task* task, const Options* opts) : 
	    Base(task, opts), 
	    abstracted(NULL) 
	    {}
	       	
    	virtual void updateWaitingEdges(const PtrSet<Location>& locs, vector<Edge*>& waitingEdges) const {
	    assert(abstracted);
    	    for (PtrSet<Location>::const_iterator it = locs.begin(); it != locs.end(); ++it) {
    		for (uint32_t i = 0; i < (*it)->getOutgoingEdges().size(); i++) {
    		    Edge* edge = (*it)->getOutgoingEdges()[i];
    		    if (!(*abstracted)[edge->id]) {
    			waitingEdges.push_back(edge);
    		    }
    		}
    	    }
    	}		
    };

    typedef FFUHeuristic<UselessHelper<FFHeuristic> > FFUselessHeuristic;
    typedef FFUHeuristic<UselessHelper<FFBackHeuristic> > FFBackUselessHeuristic;
    typedef FFUHeuristic<UselessHelper<FFAddHeuristic> > FFAddUselessHeuristic;
}

#endif /* USELESS_FF_HEURISTIC_H */
