import logging

from hashlib import sha1

from util.config.validators import BaseValidator, ConfigValidationException
from util.registry.torrent import jwt_from_infohash, TorrentConfiguration

logger = logging.getLogger(__name__)

class BittorrentValidator(BaseValidator):
  name = "bittorrent"

  @classmethod
  def validate(cls, validator_context):
    """ Validates the configuration for using BitTorrent for downloads. """
    config = validator_context.config
    client = validator_context.http_client

    announce_url = config.get('BITTORRENT_ANNOUNCE_URL')
    if not announce_url:
      raise ConfigValidationException('Missing announce URL')

    # Ensure that the tracker is reachable and accepts requests signed with a registry key.
    params = {
      'info_hash': sha1('test').digest(),
      'peer_id': '-QUAY00-6wfG2wk6wWLc',
      'uploaded': 0,
      'downloaded': 0,
      'left': 0,
      'numwant': 0,
      'port': 80,
    }

    torrent_config = TorrentConfiguration.for_testing(validator_context.instance_keys, announce_url,
                                                      validator_context.registry_title)
    encoded_jwt = jwt_from_infohash(torrent_config, params['info_hash'])
    params['jwt'] = encoded_jwt

    resp = client.get(announce_url, timeout=5, params=params)
    logger.debug('Got tracker response: %s: %s', resp.status_code, resp.text)

    if resp.status_code == 404:
      raise ConfigValidationException('Announce path not found; did you forget `/announce`?')

    if resp.status_code == 500:
      raise ConfigValidationException('Did not get expected response from Tracker; ' +
                                      'please check your settings')

    if resp.status_code == 200:
      if 'invalid jwt' in resp.text:
        raise ConfigValidationException('Could not authorize to Tracker; is your Tracker ' +
                                        'properly configured?')

      if 'failure reason' in resp.text:
        raise ConfigValidationException('Could not validate signed announce request: ' + resp.text)

      if 'go_goroutines' in resp.text:
        raise ConfigValidationException('Could not validate signed announce request: ' +
                                        'provided port is used for Prometheus')