from abc import ABCMeta, abstractmethod
from collections import namedtuple

from six import add_metaclass


class ManifestLabel(
  namedtuple('ManifestLabel', [
    'uuid',
    'key',
    'value',
    'source_type_name',
    'media_type_name',
    ])):
  """
  ManifestLabel represents a label on a manifest
  :type uuid: string
  :type key: string 
  :type value: string 
  :type source_type_name: string  
  :type media_type_name: string 
  """ 
  def to_dict(self):
    return {
      'id': self.uuid,
      'key': self.key,
      'value': self.value,
      'source_type': self.source_type_name,
      'media_type': self.media_type_name,
    }

  
class ManifestAndImage(
  namedtuple('ManifestAndImage', [
    'digest',
    'manifest_data',
    'image',
    ])):
  def to_dict(self):
    return {
      'digest': self.digest,
      'manifest_data': self.manifest_data,
      'image': self.image.to_dict(),
    }

  
@add_metaclass(ABCMeta)
class ManifestLabelInterface(object):
  """
  Data interface that the manifest labels API uses
  """
  
  @abstractmethod
  def get_manifest_labels(self, namespace_name, repository_name, manifestref, filter=None):
    """
    
    Args:
      namespace_name: string
      repository_name: string
      manifestref: string
      filter: string

    Returns:
      list(ManifestLabel) or None

    """   

  @abstractmethod
  def create_manifest_label(self, namespace_name, repository_name, manifestref, key, value, source_type_name, media_type_name):
    """
    
    Args:
      namespace_name: string
      repository_name: string
      manifestref: string
      key: string
      value: string
      source_type_name: string 
      media_type_name: string

    Returns:
      ManifestLabel or None 
    """
  
  @abstractmethod
  def get_manifest_label(self, namespace_name, repository_name, manifestref, label_uuid):
    """
    
    Args:
      namespace_name: string
      repository_name: string
      manifestref: string
      label_uuid: string

    Returns:
      ManifestLabel or None
    """
  
  @abstractmethod
  def delete_manifest_label(self, namespace_name, repository_name, manifestref, label_uuid):
    """
    
    Args:
      namespace_name: string
      repository_name: string
      manifestref: string
      label_uuid: string

    Returns:
      ManifestLabel or None
    """

  @abstractmethod
  def get_repository_manifest(self, namespace_name, repository_name, digest):
    """
    Returns the manifest and image for the manifest with the specified digest, if any.
    """