/*******************************************************************************
 * Copyright (c) 2015-2017 ONERA and IRT AESE (IRT Saint Exupéry).
 * Ce logiciel est la propriété de l’ONERA (the French Aerospace Lab) et de
 * l'IRT AESE (IRT Saint Exupéry).
 * Tous droits réservés.
 *
 * Ce programme et les éléments qui l'accompagnent sont mis à disposition
 * aux conditions définies par le contrat de licence logiciel CeCILL-C soumise
 * au droit français et respectant les principes de diffusion des logiciels libres.
 * Vous pouvez utiliser, modifier et/ou redistribuer ce programme
 * sous les conditions de la licence CeCILL-C (http://www.cecill.info).

 * This software is property of ONERA (the French Aerospace Lab) and of
 * the IRT AESE (IRT Saint Exupéry).
 * All rights reserved.
 *
 * This program and the accompanying materials are made available under
 * the terms of the CeCILL-C license under French law and
 * abiding by the rules of distribution of free software.
 * You can  use, modify and/ or redistribute the software under the terms of
 * the CeCILL-C license (http://www.cecill.info).
 *
 * Contributeurs/contributors:
 *     Guillaume Infantes (ONERA - Centre de Toulouse) - initial API and implementation
 *     Alexandre Albore (IRT Saint-Exupéry) - Altarica/Fiacre translation
 *
 *******************************************************************************/

#include "LandmarkMetaEvent.hh"
#include "AltaricaModel.hh"
#include "AltaricaState.hh"
#include "LandmarkState.hh"
#include "Transition.hh"
#include "Event.hh"
#include "MetaEvent.hh"
#include "expressions/Expression.hh"
#include "Variable.hh"
#include "Values.hh"

using namespace epoch::altarica;

LandmarkMetaEvent::LandmarkMetaEvent(MetaEvent *me, AltaricaModel *am) {
    me_ = me;   
    am_ = am;
    label_ = new AltaricaState(false,am_,am_->getInitInfo());
}



void LandmarkMetaEvent::addLabel(const AltaricaState * l) {
    l->mergeToState(label_);
}



std::string LandmarkMetaEvent::toString() const {
    std::string s;
    s += me_->toString();
    s +=  "LABELS :\n";
    s += label_->toString(true,false,false,false);
    return s;
}

void LandmarkMetaEvent::computeLabels(const AltaricaModel*am, const LandmarkState *als) {
    
    std::vector<bool> varInPreconds(am_->getNStateVars(), false);

    const std::vector<Event*> * evs = me_->getEvents();
    for (std::vector<Event*>::const_iterator evi = evs->begin(); evi != evs->end(); ++evi) {
	const std::vector<Transition*> * trans = (*evi)->getTrans();
	for (std::vector<Transition*>::const_iterator ti = trans->begin(); ti != trans->end(); ++ti) {
	    const Expression * precond = (*ti)->getPrecond();
	    std::vector<Variable*> * newvars = precond->infoVars(am, (*ti)->getNode(), false, false);	    
	    for (std::vector<Variable*>::iterator nvi = newvars->begin(); nvi != newvars->end(); ++nvi) {
		varInPreconds[(*nvi)->getIndex()] = true;
	    }
	    delete newvars;
	}
    }

    // pour chaque var à true, on prend une seule valeur, et le reste change pas,
    // si mev valide, on ajoute les labels de cette valeur (addLabel)
    // vrai car on fait l'union des labels: si une valeur d'une var d'une précond est ok, alors son 
    // label sera dans le label final

    AltaricaState *as = als->getState()->clone();    
    
    for (int i =0; i<am_->getNStateVars(); ++i) {
	if (varInPreconds[i]) {
	    Value *v = as->getStateValue(i);
	    std::vector<Value*> *afv = v->getSingletons();
	    for (std::vector<Value*>::iterator fvi = afv->begin(); fvi!= afv->end(); ++fvi) {
		// on teste une des valeurs possibles pour la variable
		as->setStateValue(i,*fvi);
		if (me_->isEnabled(am, as)) {
		    addLabel(als->getLabel(i, *fvi));
		}
	    }
	    as->setStateValue(i,v);
	    
	}
    }    
}

