#include "security/Permissions.h"
#include "util/simpleobject/AgString.h"
#include "util/StringUtils.h"
#include <boost/thread/locks.hpp>
#include <algorithm>

Permissions::Permissions()
{

}

Permissions::Permissions(const AgString& data, boost::shared_ptr<PermissionChecker> checker)
{
    ctor(data, checker);
}

Permissions::Permissions(const AgString& context, const AgString& type)
{
    permissions.push_back(PermissionPtr(new Permission(context, type)));
}

Permissions::Permissions(const AgString& data)
{
    ctor(data, PermissionCheckerPtr());
}

std::list<PermissionPtr>::iterator Permissions::iteratorBegin()
{
    return permissions.begin();
}

std::list<PermissionPtr>::iterator Permissions::iteratorEnd()
{
    return permissions.end();
}

void Permissions::ctor(const AgString& data, boost::shared_ptr<PermissionChecker> checker)
{
    std::vector<AgString> pd = StringUtils::split(data, Permissions::PERMISSIONS_SEPARATOR);

    for (std::vector<AgString>::iterator it = pd.begin(); it!=pd.end(); ++it) {
        AgString permSrc = (*it).trim();
        if (permSrc.length() > 0) {
            permissions.push_back(PermissionPtr(new Permission(permSrc, checker)));
        }
    }
}

AgString Permissions::encode()
{
    typedef std::list<PermissionPtr>::iterator permisionIter;
    AgString enc;

    boost::lock_guard<boost::mutex> lock(permissionsLock);
    {
        int i = 0;
        for (permisionIter it = permissions.begin(); it!=permissions.end(); ++it) {
            if (i > 0) {
                enc += Permissions::PERMISSIONS_SEPARATOR;
            }

            enc += (*it)->encode();

            i++;
        }
    }

    return enc;
}

AgString Permissions::toString()
{
    return encode();
}

int Permissions::size()
{
    return permissions.size();
}

Permissions& Permissions::add(PermissionPtr permission)
{
    boost::lock_guard<boost::mutex> lock(permissionsLock);
    {
        permissions.push_back(permission);
    }

    return *this;
}

bool permissComapre (PermissionPtr i, PermissionPtr j)
{
    return (i->equals(j.get()));
}

bool Permissions::equals(Permissions* obj)
{
    if (this == obj) {
        return true;
    }

    if (obj == NULL) {
        return false;
    }

    if (this->permissions.size() != obj->permissions.size())
        return false;

    return  std::equal(this->permissions.begin(), this->permissions.end(), obj->permissions.begin(), permissComapre);
}

