/*******************************************************************************
 * Copyright (c) 2015-2016 ONERA.
 * Ce logiciel est la propriété de l’ONERA (the French Aerospace Lab).
 * 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).
 * 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
 *
 *******************************************************************************/

#include "ValueBool.hh"
#include <limits.h>
#include <sstream>
#include "../domains/PredefinedDomain.hh"
#include <boost/functional/hash.hpp>

using namespace epoch::altarica;



ValueBool::ValueBool() {
    t_ = true;
    b_ = true;
}

ValueBool::ValueBool(bool t, bool b) {
    t_ = t;
    b_ = b;
}


void ValueBool::allowTop(bool t) {
    t_ = t;
}

void ValueBool::allowBottom(bool b) {
    b_ = b;
}


ValueBool * ValueBool::clone() const {
    ValueBool *nb =  new ValueBool(t_,b_);
    nb->setConstrained(constrained_);
    return nb;
}

void ValueBool::inverse() {
  bool oldb = b_;
  
    b_ = t_;
    t_ = oldb;
}

ValueBool* ValueBool::getComplement() const {
    return new ValueBool(!t_,!b_);
}



bool ValueBool::possible(bool b) const {
    if (b)
	return allowedTop();
    return allowedBottom();
}




int ValueBool::toHash() const {
    if (t_) {
	if (b_)
	    return 0;
	return 1;
    } else {
	if (b_)
	    return 2;
	return 3;
    }
}



bool ValueBool::toBool() const {
    if (t_ == !b_) {
	return t_;
    } else
	return false;
}


bool ValueBool::equals(const ValueBool*v) const {
    return (t_ == v->allowedTop() && b_ == v->allowedBottom());
}



void ValueBool::merge(const ValueBool*v) {
    t_ = t_ || v->allowedTop();
    b_ = b_ || v->allowedBottom();
}

bool ValueBool::contains(const ValueBool *fb) const {
    bool b = fb->toBool();
    return (b && t_ || !b && b_);
}





void ValueBool::intersectValue(const ValueBool* v) {
    t_=t_&&v->allowedTop();
    b_=b_&&v->allowedBottom();
}

void ValueBool::land(const ValueBool *v) {
    t_ = t_ && v->allowedTop();
    b_ = b_ || v->allowedBottom();
}

void ValueBool::lor(const ValueBool *v) {
    t_ = t_ || v->allowedTop();
    b_ = b_ && v->allowedBottom();
}

bool ValueBool::hasIntersection(const ValueBool*v) const {
    if (t_ &&  v->allowedTop())
	return true;
    if (b_ &&  v->allowedBottom())
	return true;
    return false;    
}

std::string ValueBool::toString() const {
    std::string s;
    s+="{ ";
    if (t_)
	s+= "true";
    if (t_ && b_)
	s+= " ";
    if (b_)
	s+= "false";
    s+= " }";
    return s;
}

std::vector<Value*> * ValueBool::getSingletons() const {
    std::vector<Value*> * ret = new std::vector<Value*>();
    if (t_) {
	Value *fv = new ValueBool(true,false);
	fv->own();
	ret->push_back(fv);
    }
    if (b_) {
	Value *fv = new ValueBool(false,true);
	fv->own();
	ret->push_back(fv);
    }
    return ret;
}

bool ValueBool::less(const ValueBool *v) const {
    if (t_) {
	if (b_) {
	    if (v->allowedTop() && !v->allowedBottom())
		return true;
	} else {
	    return false;
	}
    } else {
	if (b_) {
	    if (v->allowedTop())
		return true;
	} else {
	    if (v->allowedBottom() || v->allowedTop())
		return true;
	}	
    }
}

void ValueBool::removeValue(const ValueBool * v) {
    if (v->allowedTop())
	t_ = false;
    if (v->allowedBottom())
	b_ = false;
}


bool ValueBool::pDifferent(const ValueBool *v) const {
    return ((t_ &&  !v->allowedTop()) || (b_ && !v->allowedBottom()));
}
