# XXX This code is not yet ready to be run in production, and should remain disabled until such
# XXX time as this notice is removed.

import logging
import re
import jwt.utils
import yaml

from flask import make_response, request

from app import storage
from auth.jwt_auth import process_jwt_auth
from endpoints.decorators import anon_protect
from endpoints.v2 import v2_bp, require_repo_read, require_repo_write, get_input_stream
from digest import digest_tools


logger = logging.getLogger(__name__)


VALID_TAG_PATTERN = r'[\w][\w.-]{0,127}'
VALID_TAG_REGEX = re.compile(VALID_TAG_PATTERN)


class SignedManifest(object):
  SIGNATURES_KEY = 'signatures'
  PROTECTED_KEY = 'protected'
  FORMAT_LENGTH_KEY = 'formatLength'
  FORMAT_TAIL_KEY = 'formatTail'
  REPO_NAME_KEY = 'name'
  REPO_TAG_KEY = 'tag'

  def __init__(self, manifest_bytes):
    self._bytes = manifest_bytes
    parsed = yaml.safe_load(manifest_bytes)

    self._signatures = parsed[self.SIGNATURES_KEY]
    self._namespace, self._repo_name = parsed[self.REPO_NAME_KEY].split('/')
    self._tag = parsed[self.REPO_TAG_KEY]

    self._validate()

  def _validate(self):
    pass

  @property
  def signatures(self):
    return self._signatures

  @property
  def namespace(self):
    return self._namespace

  @property
  def repo_name(self):
    return self._repo_name

  @property
  def tag(self):
    return self._tag

  @property
  def payload(self):
    protected = self._signatures[0][self.PROTECTED_KEY]
    parsed_protected = yaml.safe_load(jwt.utils.base64url_decode(protected))
    logger.debug('parsed_protected: %s', parsed_protected)
    signed_content_head = self._bytes[:parsed_protected[self.FORMAT_LENGTH_KEY]]
    logger.debug('signed content head: %s', signed_content_head)
    signed_content_tail = jwt.utils.base64url_decode(parsed_protected[self.FORMAT_TAIL_KEY])
    logger.debug('signed content tail: %s', signed_content_tail)
    return signed_content_head + signed_content_tail


@v2_bp.route('/<namespace>/<repo_name>/manifests/<regex("' + VALID_TAG_PATTERN + '"):tag_name>',
             methods=['GET'])
@process_jwt_auth
@require_repo_read
@anon_protect
def fetch_manifest_by_tagname(namespace, repo_name, tag_name):
  logger.debug('Fetching tag manifest with name: %s', tag_name)
  return make_response('Manifest {0}'.format(tag_name))


@v2_bp.route('/<namespace>/<repo_name>/manifests/<regex("' + VALID_TAG_PATTERN + '"):tag_name>',
             methods=['PUT'])
@process_jwt_auth
@require_repo_write
@anon_protect
def write_manifest_by_tagname(namespace, repo_name, tag_name):
  manifest = SignedManifest(request.data)
  manifest_digest = digest_tools.sha256_digest(manifest.payload)

  response = make_response('OK', 202)
  response.headers['Docker-Content-Digest'] = manifest_digest
  response.headers['Location'] = 'https://fun.com'
  return response


# @v2_bp.route('/<namespace>/<repo_name>/manifests/<regex("' + digest_tools.DIGEST_PATTERN + '"):tag_digest>',
#              methods=['PUT'])
# @process_jwt_auth
# @require_repo_write
# @anon_protect
# def write_manifest(namespace, repo_name, tag_digest):
#   logger.debug('Writing tag manifest with name: %s', tag_digest)

#   manifest_path = digest_tools.content_path(tag_digest)
#   storage.stream_write('local_us', manifest_path, get_input_stream(request))

#   return make_response('Manifest {0}'.format(tag_digest))