/* ***** BEGIN LICENSE BLOCK *****
 * FW4SPL - Copyright (C) IRCAD, 2009-2012.
 * Distributed under the terms of the GNU Lesser General Public License (LGPL) as
 * published by the Free Software Foundation.
 * ****** END LICENSE BLOCK ****** */

#ifndef _FWDATA_PROCESSOBJECT_HPP_
#define _FWDATA_PROCESSOBJECT_HPP_

#include <map>
#include <vector>

#include "fwData/Object.hpp"
#include "fwData/factory/new.hpp"

fwCorePredeclare( (fwData)(Field) );


fwCampAutoDeclareDataMacro((fwData)(ProcessObject), FWDATA_API);

namespace fwData
{
/**
 * @class   ProcessObject
 * @brief   Provides the notion of Process Object: object having inputs and outputs
 * 
 * @date    2007-2009.
 */
class FWDATA_CLASS_API ProcessObject : public Object
{
public:
    fwCoreClassDefinitionsWithFactoryMacro( (ProcessObject)(::fwData::Object), (()), ::fwData::factory::New< ProcessObject >) ;


    fwCampMakeFriendDataMacro((fwData)(ProcessObject));

    typedef std::string ParamNameType;
    typedef std::vector<std::string> ParamNameVectorType;
    typedef std::map< ParamNameType, ::fwData::Object::sptr > ProcessObjectMapType;

    /**
     * @brief Constructor
     * @param key Private construction key
     */
    FWDATA_API ProcessObject(::fwData::Object::Key key) ;

    /**
     * @brief   Destructor
     */
    FWDATA_API virtual ~ProcessObject();

    /**
     * @brief Retrieves the input data associated with specified name (null if non exist).
     * @param[in] name Input name
     * @return null sptr if input is not found
     */
    FWDATA_API ::fwData::Object::sptr getInput(const ParamNameType& name);

    /**
     * @brief Retrieves the input data associated with specified name type OBJECTTYPE (null if non exist).
     * @param[in] name Input name
     * @return null sptr if input is not found
     */
    template< class OBJECTTYPE >
    typename OBJECTTYPE::sptr getInput(const ParamNameType& name)
    {
        return OBJECTTYPE::dynamicCast( this->getInput( name ) ) ;
    }

    /**
     * @brief Retrieves the output data associated with specified name (null if non exist).
     * @param[in] name Output name
     * @return null sptr if output is not found
     */
    FWDATA_API ::fwData::Object::sptr getOutput(const ParamNameType& name);

    /**
     * @brief Retrieves the output data associated with specified name type OBJECTTYPE (null if non exist).
     * @param[in] name Output name
     * @return null sptr if output is not found
     */
    template< class OBJECTTYPE >
    typename OBJECTTYPE::sptr getOutput(const ParamNameType& name)
    {
        return OBJECTTYPE::dynamicCast( this->getOutput( name ) ) ;
    }

    /// Retrieve the input data
    fwDataGetSetCRefMacro(Inputs, ProcessObjectMapType);

    /// Retrieve the output data
    fwDataGetSetCRefMacro(Outputs, ProcessObjectMapType);

    /**
     * @brief Register input value with specified name.
     * If the name does already exist, the matching value will be replaced.
     * @param[in] name Input name
     * @param[in] object  Input value
     */
    FWDATA_API void setInputValue(const ParamNameType& name, ::fwData::Object::sptr object);

    /**
     * @brief Register output value with specified name.
     * If the name does already exist, the matching value will be replaced.
     * @param[in] name Output name
     * @param[in] object  Output value
     */
    FWDATA_API void setOutputValue(const ParamNameType& name, ::fwData::Object::sptr object);

    /**
     * @brief Returns vector of input parameters names.
     */
    FWDATA_API ParamNameVectorType getInputsParamNames() const;

    /**
     * @brief Returns vector of output parameters names.
     */
    FWDATA_API ParamNameVectorType getOutputsParamNames() const;

    /**
     * @brief Unregister all inputs parameters.
     */
    FWDATA_API void clearInputs();

    /**
     * @brief Unregister all output parameters.
     */
    FWDATA_API void clearOutputs();

    /// Defines shallow copy
    FWDATA_API void shallowCopy( const Object::csptr& source );

    /// Defines deep copy
    FWDATA_API void cachedDeepCopy(const Object::csptr& source, DeepCopyCacheType &cache);

protected:

    /**
     * @brief Returns vector of parameters names from params map.
     */
    FWDATA_API ParamNameVectorType getParamNames(const ProcessObjectMapType& params) const;

    /**
     * @brief Register value with specified name in params map.
     * If the name does already exist, the matching value will be replaced.
     * @param[in] name Param name
     * @param[in] object  Param
     * @param params parameters map to insert object
     */
    FWDATA_API void setValue(const ParamNameType& name, ::fwData::Object::sptr object, ProcessObjectMapType& params);

    /**
     * @brief Retrieves data associated with specified name in params map (null if non exist).
     * @param[in] name Param name
     * @param params parameters map containing the data
     * @return null sptr if param is not found
     */
    FWDATA_API ::fwData::Object::sptr getValue(const ParamNameType& name, const ProcessObjectMapType& params);

    /**
     * @brief Unregister all parameters in params map.
     */
    FWDATA_API void clearParams(ProcessObjectMapType& params);

    /// Inputs values map
    ProcessObjectMapType m_attrInputs;

    /// Outputs values map
    ProcessObjectMapType m_attrOutputs;
};

} // namespace fwData


#endif //_FWDATA_PROCESSOBJECT_HPP_
