#!/usr/bin/env python

from datetime import datetime, timedelta
from urlparse import urlunparse

from jinja2 import Template
from cachetools import lru_cache

import logging
import release
import os.path

from app import app
from data.model import ServiceKeyDoesNotExist
from data.model.release import set_region_release
from data.model.service_keys import get_service_key
from util.config.database import sync_database_with_config
from util.generatepresharedkey import generate_key
from  _init import CONF_DIR


logger = logging.getLogger(__name__)


@lru_cache(maxsize=1)
def get_audience():
  audience = app.config.get('JWTPROXY_AUDIENCE')

  if audience:
    return audience

  scheme = app.config.get('PREFERRED_URL_SCHEME')
  hostname = app.config.get('SERVER_HOSTNAME')

  # hostname includes port, use that
  if ':' in hostname:
    return urlunparse((scheme, hostname, '', '', '', ''))

  # no port, guess based on scheme
  if scheme == 'https':
    port = '443'
  else:
    port = '80'

  return urlunparse((scheme, hostname + ':' + port, '', '', '', ''))


def setup_jwt_proxy():
  """
  Creates a service key for quay to use in the jwtproxy and generates the JWT proxy configuration.
  """
  if os.path.exists(os.path.join(CONF_DIR, 'jwtproxy_conf.yaml')):
    # Proxy is already setup. Make sure the service key is still valid.
    try:
      with open(app.config['INSTANCE_SERVICE_KEY_KID_LOCATION']) as f:
        quay_key_id = f.read()

      try:
        get_service_key(quay_key_id, approved_only=False)
        return
      except ServiceKeyDoesNotExist:
        logger.exception('Could not find non-expired existing service key %s; creating a new one',
                         quay_key_id)

      # Found a valid service key, so exiting.
    except IOError:
      logger.exception('Could not load existing service key; creating a new one')

  # Generate the key for this Quay instance to use.
  minutes_until_expiration = app.config.get('INSTANCE_SERVICE_KEY_EXPIRATION', 120)
  expiration = datetime.now() + timedelta(minutes=minutes_until_expiration)
  quay_key, quay_key_id = generate_key(app.config['INSTANCE_SERVICE_KEY_SERVICE'],
                                       get_audience(), expiration_date=expiration)

  with open(app.config['INSTANCE_SERVICE_KEY_KID_LOCATION'], mode='w') as f:
    f.truncate(0)
    f.write(quay_key_id)

  with open(app.config['INSTANCE_SERVICE_KEY_LOCATION'], mode='w') as f:
    f.truncate(0)
    f.write(quay_key.exportKey())

  # Generate the JWT proxy configuration.
  audience = get_audience()
  registry = audience + '/keys'
  security_issuer = app.config.get('SECURITY_SCANNER_ISSUER_NAME', 'security_scanner')

  with open(os.path.join(CONF_DIR, 'jwtproxy_conf.yaml.jnj')) as f:
    template = Template(f.read())
    rendered = template.render(
      conf_dir=CONF_DIR,
      audience=audience,
      registry=registry,
      key_id=quay_key_id,
      security_issuer=security_issuer,
    )

  with open(os.path.join(CONF_DIR, 'jwtproxy_conf.yaml'), 'w') as f:
    f.write(rendered)


def main():
  if app.config.get('SETUP_COMPLETE', False):
    sync_database_with_config(app.config)
    setup_jwt_proxy()

  # Record deploy
  if release.REGION and release.GIT_HEAD:
    set_region_release(release.SERVICE, release.REGION, release.GIT_HEAD)


if __name__ == '__main__':
  main()