from abc import ABCMeta, abstractmethod
from collections import namedtuple

from six import add_metaclass


class Permission(namedtuple('Permission', ['repository_name', 'repository_visibility_name', 'role_name'])):
  """
  Permission the relationship between a robot and a repository and whether that robot can see the repo.
  """

  def to_dict(self):
    return {
      'repository': {
        'name': self.repository_name,
        'is_public': self.repository_visibility_name == 'public'
      },
      'role': self.role_name
    }


class Team(namedtuple('Team', ['name', 'avatar'])):
  """
  Team represents a team entry for a robot list entry.
  :type name: string
  :type avatar: {string -> string}
  """
  def to_dict(self):
    return {
      'name': self.name,
      'avatar': self.avatar,
    }


class RobotWithPermissions(
  namedtuple('RobotWithPermissions', [
    'name',
    'password',
    'teams',
    'repository_names',
  ])):
  """
  RobotWithPermissions is a list of robot entries.
  :type name: string
  :type password: string
  :type teams: [Team]
  :type repository_names: [string]

  """

  def to_dict(self):
    return {
      'name': self.name,
      'token': self.password,
      'teams': [team.to_dict() for team in self.teams],
      'repositories': self.repository_names
    }


class Robot(
  namedtuple('Robot', [
    'name',
    'password',
  ])):
  """
  Robot represents a robot entity.
  :type name: string
  :type password: string

  """

  def to_dict(self):
    return {
      'name': self.name,
      'token': self.password
    }


@add_metaclass(ABCMeta)
class RobotInterface(object):
  """
  Interface that represents all data store interactions required by the Robot API
  """

  @abstractmethod
  def get_org_robot(self, robot_shortname, orgname):
    """

    Returns:
      Robot object

    """

  @abstractmethod
  def get_user_robot(self, robot_shortname, owning_user):
    """

    Returns:
      Robot object

    """

  @abstractmethod
  def create_user_robot(self, robot_shortname, owning_user):
    """

    Returns:
      Robot object

    """

  @abstractmethod
  def create_org_robot(self, robot_shortname, orgname):
    """

    Returns:
      Robot object

    """

  @abstractmethod
  def delete_robot(self, robot_username):
    """

    Returns:
      Robot object

    """

  @abstractmethod
  def regenerate_user_robot_token(self, robot_shortname, owning_user):
    """

    Returns:
      Robot object

    """

  @abstractmethod
  def regenerate_org_robot_token(self, robot_shortname, orgname):
    """

    Returns:
      Robot object

    """

  @abstractmethod
  def list_entity_robot_permission_teams(self, prefix, include_permissions=False):
    """

    Returns:
      list of RobotWithPermissions objects

    """

  @abstractmethod
  def list_robot_permissions(self, username):
    """

    Returns:
      list of Robot objects

    """