import sys
from abc import ABCMeta, abstractmethod
from collections import namedtuple

from six import add_metaclass


class SaveException(Exception):
    def __init__(self, other):
        self.traceback = sys.exc_info()
        super(SaveException, self).__init__(str(other))


class DeleteException(Exception):
    def __init__(self, other):
        self.traceback = sys.exc_info()
        super(DeleteException, self).__init__(str(other))


class Role(namedtuple("Role", ["role_name"])):
    def to_dict(self):
        return {
            "role": self.role_name,
        }


class UserPermission(
    namedtuple(
        "UserPermission",
        [
            "role_name",
            "username",
            "is_robot",
            "avatar",
            "is_org_member",
            "has_org",
        ],
    )
):
    def to_dict(self):
        perm_dict = {
            "role": self.role_name,
            "name": self.username,
            "is_robot": self.is_robot,
            "avatar": self.avatar,
        }
        if self.has_org:
            perm_dict["is_org_member"] = self.is_org_member
        return perm_dict


class RobotPermission(
    namedtuple(
        "RobotPermission",
        [
            "role_name",
            "username",
            "is_robot",
            "is_org_member",
        ],
    )
):
    def to_dict(self, user=None, team=None, org_members=None):
        return {
            "role": self.role_name,
            "name": self.username,
            "is_robot": True,
            "is_org_member": self.is_org_member,
        }


class TeamPermission(
    namedtuple(
        "TeamPermission",
        [
            "role_name",
            "team_name",
            "avatar",
        ],
    )
):
    def to_dict(self):
        return {
            "role": self.role_name,
            "name": self.team_name,
            "avatar": self.avatar,
        }


@add_metaclass(ABCMeta)
class PermissionDataInterface(object):
    """
    Data interface used by permissions API.
    """

    @abstractmethod
    def get_repo_permissions_by_user(self, namespace_name, repository_name):
        """

        Args:
          namespace_name: string
          repository_name: string

        Returns:
          list(UserPermission)
        """

    @abstractmethod
    def get_repo_roles(self, username, namespace_name, repository_name):
        """

        Args:
          username: string
          namespace_name: string
          repository_name: string

        Returns:
          list(Role) or None
        """

    @abstractmethod
    def get_repo_permission_for_user(self, username, namespace_name, repository_name):
        """

        Args:
          username: string
          namespace_name: string
          repository_name: string

        Returns:
          UserPermission
        """

    @abstractmethod
    def set_repo_permission_for_user(self, username, namespace_name, repository_name, role_name):
        """

        Args:
          username: string
          namespace_name: string
          repository_name: string
          role_name: string

        Returns:
          UserPermission

        Raises:
          SaveException
        """

    @abstractmethod
    def delete_repo_permission_for_user(self, username, namespace_name, repository_name):
        """

        Args:
          username: string
          namespace_name: string
          repository_name: string

        Returns:
          void

        Raises:
          DeleteException
        """

    @abstractmethod
    def get_repo_permissions_by_team(self, namespace_name, repository_name):
        """

        Args:
          namespace_name: string
          repository_name: string

        Returns:
          list(TeamPermission)
        """

    @abstractmethod
    def get_repo_role_for_team(self, team_name, namespace_name, repository_name):
        """

        Args:
          team_name: string
          namespace_name: string
          repository_name: string

        Returns:
          Role
        """

    @abstractmethod
    def set_repo_permission_for_team(self, team_name, namespace_name, repository_name, permission):
        """

        Args:
          team_name: string
          namespace_name: string
          repository_name: string
          permission: string

        Returns:
          TeamPermission

        Raises:
          SaveException
        """

    @abstractmethod
    def delete_repo_permission_for_team(self, team_name, namespace_name, repository_name):
        """

        Args:
          team_name: string
          namespace_name: string
          repository_name: string

        Returns:
          TeamPermission

        Raises:
          DeleteException
        """

[((20, 11, 20, 44), 'collections.namedtuple', 'namedtuple', ({(20, 22, 20, 28): '"""Role"""', (20, 30, 20, 43): "['role_name']"}, {}), "('Role', ['role_name'])", False, 'from collections import namedtuple\n'), ((28, 4, 38, 5), 'collections.namedtuple', 'namedtuple', ({(29, 8, 29, 24): '"""UserPermission"""', (30, 8, 37, 9): "['role_name', 'username', 'is_robot', 'avatar', 'is_org_member', 'has_org']"}, {}), "('UserPermission', ['role_name', 'username', 'is_robot', 'avatar',\n    'is_org_member', 'has_org'])", False, 'from collections import namedtuple\n'), ((53, 4, 61, 5), 'collections.namedtuple', 'namedtuple', ({(54, 8, 54, 25): '"""RobotPermission"""', (55, 8, 60, 9): "['role_name', 'username', 'is_robot', 'is_org_member']"}, {}), "('RobotPermission', ['role_name', 'username', 'is_robot',\n    'is_org_member'])", False, 'from collections import namedtuple\n'), ((73, 4, 80, 5), 'collections.namedtuple', 'namedtuple', ({(74, 8, 74, 24): '"""TeamPermission"""', (75, 8, 79, 9): "['role_name', 'team_name', 'avatar']"}, {}), "('TeamPermission', ['role_name', 'team_name', 'avatar'])", False, 'from collections import namedtuple\n'), ((90, 1, 90, 23), 'six.add_metaclass', 'add_metaclass', ({(90, 15, 90, 22): 'ABCMeta'}, {}), '(ABCMeta)', False, 'from six import add_metaclass\n'), ((10, 25, 10, 39), 'sys.exc_info', 'sys.exc_info', ({}, {}), '()', False, 'import sys\n'), ((16, 25, 16, 39), 'sys.exc_info', 'sys.exc_info', ({}, {}), '()', False, 'import sys\n')]