#pragma once

#include <maps/wikimap/mapspro/libs/acl/include/common.h>

#include <set>
#include <vector>

namespace maps::wiki::acl {

class Permission;
class Policy;
class Group;

class Role
{
public:
    friend class Factory;
    enum class Privacy
    {
        Public,
        Private
    };
    static Privacy privacy(bool isPublic)
    { return isPublic ? Privacy::Public : Privacy::Private; }

    ID id() const { return id_; }

    const std::string& name() const { return name_; }
    void setName(const std::string& newName);

    const std::string& description() const { return description_; }
    void setDescription(const std::string& newDescription);

    bool isPublic() const { return privacy_ == Privacy::Public; }
    Privacy privacy() const { return privacy_; }
    void setPrivacy(Privacy privacy);

    void add(const Permission& permission) const;
    void remove(const Permission& permission) const;
    void removePermissions() const;
    bool setPermissions(std::vector<Permission> newPermissions) const;

    std::vector<Permission> permissions() const;
    std::vector<Policy> policies() const;
    std::set<ID> leafPermissionsIds() const;

    void addCanAssignRole(const Role& role);
    void addCanAssignGroup(const Group& group);
    void removeCanAssignRole(const Role& role);
    void removeCanAssignGroup(const Group& group);
    std::vector<Role> canAssignRoles() const;
    std::vector<Group> canAssignGroups() const;

private:
    Role(
        ID id,
        const std::string& name,
        const std::string& description,
        Privacy privacy,
        Transaction& work);

    ID id_;
    std::string name_;
    std::string description_;
    Privacy privacy_;
    Transaction& work_;
};

} // namespace maps::wiki::acl
