#ifndef CPPCADESCOLLECTION_H_
#define CPPCADESCOLLECTION_H_

#include <vector>
#include "cplib/Blob.h"
#include "cppcades.h"
#include "CPPCadesCPOID.h"

namespace CryptoPro {
namespace PKI {
namespace CAdES {

class CPPCadesCPSignerObject;
class CPPCadesCPEKUObject;
class CPPCadesCPCertificateObject;

template <class T> class CPPCadesCollection
{
public:
    CPPCadesCollection<T>(void);
    ~CPPCadesCollection<T>(void);

    HRESULT Add(const boost::shared_ptr<T>& value);
    HRESULT get_Count(unsigned int* pVal);
    HRESULT get_Item(long Index, boost::shared_ptr<T>& pVal);
    HRESULT Clear();
    HRESULT Remove(long Index);
    std::vector<boost::shared_ptr<T> > m_value;
private:
    DISALLOW_COPY_AND_ASSIGN(CPPCadesCollection<T>);
};

template <class T>
CPPCadesCollection<T>::CPPCadesCollection(void)
{
}

template <class T>
CPPCadesCollection<T>::~CPPCadesCollection(void)
{
}

template <class T>
HRESULT CPPCadesCollection<T>::Add(const boost::shared_ptr<T>& value)
{
    m_value.push_back(value);
    return S_OK;
}

template <class T>
HRESULT CPPCadesCollection<T>::get_Count(unsigned int* pVal)
{
    try
    {
        *pVal = (unsigned int)m_value.size();
    }
    CPPCADESCATCH;
    return S_OK;
}

template <class T>
HRESULT CPPCadesCollection<T>::get_Item(long Index, boost::shared_ptr<T>& pVal)
{
    if (1 > Index || m_value.size() < (unsigned int)Index)
        return E_INVALIDARG;
    CPPCADESTRYCATCH(pVal = m_value.at(--Index));
    return S_OK;
}

template <class T>
HRESULT CPPCadesCollection<T>::Clear()
{
    CPPCADESTRYCATCH(m_value.clear());
    return S_OK;
}

template <class T>
HRESULT CPPCadesCollection<T>::Remove(long Index)
{
    try
    {
        if (Index < 1 || Index > (long)m_value.size())
        {
            return E_INVALIDARG;
        }
        
        for (typename std::vector<boost::shared_ptr<T> >::iterator it = m_value.begin();
            it != m_value.end(); ++it)
        {
            if ((--Index) == 0)
            {
                m_value.erase(it);
                break;
            }
        }
    }
    CPPCADESCATCH;
    return S_OK;
}

typedef CPPCadesCollection<CBlob> CPPCadesCPBlobsObject;

typedef CPPCadesCollection<CPPCadesCPSignerObject> CPPCadesCPSignersObject;

typedef CPPCadesCollection<CPPCadesCPOIDObject> CPPCadesCPOIDsObject;

typedef CPPCadesCollection<CPPCadesCPCertificateObject> CPPCadesCPRecipientsObject;

typedef CPPCadesCollection<CPPCadesCPEKUObject> CPPCadesCPEKUsObject;

} /* namespace CAdES */
} /* namespace PKI */
} /* namespace CryptoPro */

#endif //CPPCADESCOLLECTION_H_
