import urllib
import re

import anunidecode # Don't listen to pylint's lies. This import is required for unidecode below.

from uuid import uuid4

REPOSITORY_NAME_REGEX = re.compile(r'^[\.a-zA-Z0-9_-]+$')

VALID_TAG_PATTERN = r'[\w][\w.-]{0,127}'
FULL_TAG_PATTERN = r'^[\w][\w.-]{0,127}$'

TAG_REGEX = re.compile(FULL_TAG_PATTERN)
TAG_ERROR = ('Invalid tag: must match [A-Za-z0-9_.-], NOT start with "." or "-", '
             'and can contain 1-128 characters')

def escape_tag(tag, default='latest'):
  """ Escapes a Docker tag, ensuring it matches the tag regular expression. """
  if not tag:
    return default

  tag = re.sub(r'^[^\w]', '_', tag)
  tag = re.sub(r'[^\w\.-]', '_', tag)
  return tag[0:127]


def parse_namespace_repository(repository, library_namespace, include_tag=False):
  repository = repository.encode('unidecode', 'ignore')

  parts = repository.rstrip('/').split('/', 1)
  if len(parts) < 2:
    namespace = library_namespace
    repository = parts[0]
  else:
    (namespace, repository) = parts

  if include_tag:
    parts = repository.split(':', 1)
    if len(parts) < 2:
      tag = 'latest'
    else:
      (repository, tag) = parts

  repository = urllib.quote_plus(repository)
  if include_tag:
    return (namespace, repository, tag)
  return (namespace, repository)


def format_robot_username(parent_username, robot_shortname):
  return '%s+%s' % (parent_username, robot_shortname)


def parse_robot_username(robot_username):
  if not '+' in robot_username:
    return None

  return robot_username.split('+', 2)


def parse_urn(urn):
  """ Parses a URN, returning a pair that contains a list of URN
      namespace parts, followed by the URN's unique ID.
  """
  if not urn.startswith('urn:'):
    return None

  parts = urn[len('urn:'):].split(':')
  return (parts[0:len(parts) - 1], parts[len(parts) - 1])


def parse_single_urn(urn):
  """ Parses a URN, returning a pair that contains the first
      namespace part, followed by the URN's unique ID.
  """
  result = parse_urn(urn)
  if result is None or not len(result[0]):
    return None

  return (result[0][0], result[1])

uuid_generator = lambda: str(uuid4())


def urn_generator(namespace_portions, id_generator=uuid_generator):
  prefix = 'urn:%s:' % ':'.join(namespace_portions)
  def generate_urn():
    return prefix + id_generator()
  return generate_urn