/*******************************************************************************
 * 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 "ExpressionLOG.hh"
#include "ExpressionARITH.hh"
#include "ExpressionMEMBER.hh"
#include "ExpressionPAREN.hh"
#include "ExpressionCASE.hh"

#include "Variable.hh"

using namespace epoch::altarica;

std::pair<Variable*,Variable*> * ExpressionLOG::isSimpleAffect(const AltaricaModel *am, Node *n) {
    ExpressionMEMBER * ml = dynamic_cast<ExpressionMEMBER*>(left_);
    if (ml == NULL)
	return NULL;
    ExpressionMEMBER * mr = dynamic_cast<ExpressionMEMBER*>(right_);
    if (mr == NULL)
	return NULL;


    std::vector<Variable*> * fvl = left_->infoVars(am, n,true, false);
    if (fvl->size() != 1) {
	delete fvl;
	return NULL;
    }
    if ((*fvl)[0]->isState()) {
	delete fvl;
	return NULL;
    }
    std::vector<Variable*> * fvr = right_->infoVars(am, n,true, false);
    if (fvr->size() != 1) {
	delete fvl;
	delete fvr;
	return NULL;
    }
    if ((*fvr)[0]->isState()) {
	delete fvl;
	delete fvr;
	return NULL;
    }

    std::pair<Variable*,Variable*> * ret = new std::pair<Variable*,Variable*>((*fvl)[0],(*fvr)[0]);
    delete fvr;
    delete fvl;
    return ret;
    


    return NULL;
}

	    

ExpressionLOG * ExpressionLOG::clone() const {
    ExpressionLOG * nel = new ExpressionLOG(left_->clone(), right_->clone());
    switch(log_type_) {
    case 0: nel->setEquals(); break;
    case 1: nel->setNotEquals(); break;
    case 2: nel->setImplies(); break;
    }
    return nel;    
}


std::string ExpressionLOG::toString() const {
    std::string s;
    s+= left_->toString();
    switch (log_type_) {
    case 0: s+= "=";  break;
    case 1: s+= "<>";  break;
    case 2: s+= "=>";  break;
    }
    s+= right_->toString();
    return s;
}

std::string ExpressionLOG::toString(const Node *n, const AltaricaModel& am) const {
    std::string s;
    s+= left_->toString(n, am);
    switch (log_type_) {
    case 0: s+= "=";  break;
    case 1: s+= "<>";  break;
    case 2: s+= "=>";  break;
    }
    s+= right_->toString(n, am);
    return s;
}


std::string ExpressionLOG::toString(const Node *n, const std::pair<std::string,std::string> *f, const AltaricaModel& am) const {
    std::string s;
    s+= left_->toString(n, f, am);

    if (const ExpressionPAREN* tamer = dynamic_cast<const ExpressionPAREN*>(right_)) {
	    if (const ExpressionCASE* c = dynamic_cast<const ExpressionCASE*>(tamer->getExpr())) {

		    switch (log_type_) {
		    case 0: s+= ":=";  break;
		    case 1: s+= "<>";  break;
		    case 2: s+= "=>";  break;
		    }

		    return c->toFiacre(n, f, am, s);
	    }
    }
    switch (log_type_) {
    case 0: s+= "=";  break;
    case 1: s+= "<>";  break;
    case 2: s+= "=>";  break;
    }

    s+= right_->toString(n, f, am);

    return s;
}

ExpressionLOG::~ExpressionLOG() {
    delete left_; 
    delete right_;
}
