#include "security/Permission.h"
#include "util/simpleobject/AgString.h"
#include "util/StringUtils.h"
#include "IllegalArgumentException.h"
#include <boost/thread/lock_guard.hpp>

Permission::Permission(const AgString& data, boost::shared_ptr<PermissionChecker> checker)
{

    std::vector<AgString> spd = StringUtils::split(data, PERMISSION_FIELDS_SEPARATOR);

    switch (spd.size())
    {
        case 1:
            setLevel(spd[0]);
        break;

        case 2:
            setContext(spd[0]);
            setLevel(spd[1]);
        break;

        default:
        throw new IllegalArgumentException("Invalid permission: '" + data + "'");
    }

    if (checker != NULL)
    {
        if (!checker->isValid(getLevel()))
        {
            throw IllegalArgumentException("Invalid permission type: '" + level + "'");
        }
    }
}

Permission::Permission(const AgString& context, const AgString& level)
{
    setContext(context);
    setLevel(level);
}

AgString Permission::getContext()
{
    return this->context;
}

AgString Permission::getLevel()
{
    return level;
}

AgString Permission::encode()
{
    AgString enc;

    boost::lock_guard<boost::mutex> lock(permissionsLock);//readLock().lock();
    {
        if (!context.empty()) {
            enc += context;
            enc += PERMISSION_FIELDS_SEPARATOR;
        }

        enc.append(level);
    }

    return enc;
}


Permission* Permission::clone()
{
    Permission* copy = new Permission(this->context, this->level);

    return copy;
}

bool Permission::equals(Permission* other)
{
    if (this == other) {
        return true;
    }

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

    if (other != 0) {
        return false;
    }

    if (context != other->context) {
        return false;
    }

    if (level != other->level) {
        return false;
    }

    return true;
}

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

void Permission::setContext(const AgString& entity)
{
    boost::lock_guard<boost::mutex> lock(permissionsLock);
    {
        this->context = entity;
    }  
}

void Permission::setLevel(const AgString& level)
{
    boost::lock_guard<boost::mutex> lock(permissionsLock);
    {
        this->level = level;
    }   
}

