/******************************************************************************
*       SOFA, Simulation Open-Framework Architecture, version 1.0 RC 1        *
*                (c) 2006-2011 MGH, INRIA, USTL, UJF, CNRS                    *
*                                                                             *
* This library is free software; you can redistribute it and/or modify it     *
* under the terms of the GNU Lesser General Public License as published by    *
* the Free Software Foundation; either version 2.1 of the License, or (at     *
* your option) any later version.                                             *
*                                                                             *
* This library is distributed in the hope that it will be useful, but WITHOUT *
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or       *
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License *
* for more details.                                                           *
*                                                                             *
* You should have received a copy of the GNU Lesser General Public License    *
* along with this library; if not, write to the Free Software Foundation,     *
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301 USA.          *
*******************************************************************************
*                               SOFA :: Modules                               *
*                                                                             *
* Authors: The SOFA Team and external contributors (see Authors.txt)          *
*                                                                             *
* Contact information: contact@sofa-framework.org                             *
******************************************************************************/

#include "ClosestRejectROIEngine.h"



namespace sofa
{

namespace component
{

namespace engine
{




template<class T>
ClosestRejectROIEngine<T>::ClosestRejectROIEngine()
    : Inherit1()
    , i_input(initData(&i_input,"input","closest primitives with weights, normal, distance"))
    , i_rejectROI(initData(&i_rejectROI, SetIndex(), "rejectROI", "list of indices from target (typically the boundary), that if selected, will cancel correspondences"))
    , o_output(initData(&o_output,"output","list of kept indices"))
{
    this->addAlias(&i_input, "closests");
}




template<class T>
void ClosestRejectROIEngine<T>::init()
{
    addInput(&i_input);
    addInput(&i_rejectROI);

    addOutput(&o_output);

    // track these Data to check if they changed since the last update
    m_dataTracker.trackData(i_rejectROI);

    reinit();
    Inherit1::init();
}


template<class T>
void ClosestRejectROIEngine<T>::reinit()
{
    Inherit1::reinit();

    rejectROI.clear();
    rejectROI.insert(this->i_rejectROI.getValue().begin(), this->i_rejectROI.getValue().end());

    o_output.setDirtyValue();
//    update();
}



template<class T>
void ClosestRejectROIEngine<T>::update()
{
    const std::vector<ClosestStruct>& closests = i_input.getValue();

    if( m_dataTracker.isDirty(i_rejectROI) )
    {
        rejectROI.clear();
        rejectROI.insert(this->i_rejectROI.getValue().begin(), this->i_rejectROI.getValue().end());
    }

    cleanDirty();

    std::list<size_t>& output = *o_output.beginWriteOnly();

    output.clear();

    for(size_t i=0;i<closests.size();++i)
    {
        if( !inRejectROI(closests[i]) )
            output.push_back(i);
    }

    o_output.endEdit();
}


template <class T>
bool ClosestRejectROIEngine< T >::inRejectROI(ClosestStruct const& closest)
{
    if (rejectROI.empty()) return false;
    switch (closest.indexWeightSet.size()) {
    case 3:
        return false;
    case 1: {
        typename std::set<IndexToWeightPair>::const_iterator it1 = closest.indexWeightSet.begin();
        return rejectROI.find(it1->first)!=rejectROI.end();
    }
    case 2: {
        typename std::set<IndexToWeightPair>::const_iterator it1 = closest.indexWeightSet.begin();
        typename std::set<IndexToWeightPair>::const_iterator it2 = closest.indexWeightSet.begin(); ++it2;
        return rejectROI.find(it1->first)!=rejectROI.end() && rejectROI.find(it2->first)!=rejectROI.end();
    }
    }
    return false;
}



} // namespace engine

} // namespace component

} // namespace sofa

