# Path: locksmith/common.py
# def enum(name, **enums):
#     def __iter__(self):
# def get_signature(params, signkey):
# def apicall(url, signkey, **params):
# def cache(seconds = 900):
#     def doCache(f):
#         def x(*args, **kwargs):
#     E = type(name or 'Enum', (), enums)
# API_OPERATING_STATUSES = (
#     (1, 'Normal'),
#     (2, 'Degraded Service'),
#     (3, 'Service Disruption'),
#     (4, 'Undergoing Maintenance')
# )
# API_STATUSES = enum('ApiStatuses',
#                     Stealth=0,
#                     Active=1,
#                     Deprecated=2,
#                     Disabled=3)
# KEY_STATUSES = (
#     ('U', 'Unactivated'),
#     ('A', 'Active'),
#     ('S', 'Suspended')
# )
# UNPUBLISHED, PUBLISHED, NEEDS_UPDATE = range(3)
# PUB_STATUSES = (
#     (UNPUBLISHED, 'Unpublished'),
#     (PUBLISHED, 'Published'),
#     (NEEDS_UPDATE, 'Needs Update'),
# )


import urllib2
from urlparse import urljoin
from locksmith.common import apicall, UNPUBLISHED, PUBLISHED, NEEDS_UPDATE
from celery.task import task
from django.conf import settings

@task(max_retries=5)
def push_key(key, replicate_too=True):
    if replicate_too:
        for kps in key.pub_statuses.filter(api__push_enabled=True):
            if kps.api.name in ReplicatedApiNames:
                replicate_key.delay(key, kps.api)

    endpoints = {UNPUBLISHED: 'create_key/', NEEDS_UPDATE: 'update_key/'}
    dirty = key.pub_statuses.exclude(status=PUBLISHED).filter(
              api__push_enabled=True).select_related()
    if not dirty:
        print u"Skipping push_key for {k} because all KeyPublicationStatus objects are PUBLISHED.".format(k=key.key)

    # Retrying immediately on failure would allow a broken or unresponsive
    # api to prevent other, properly functioning apis from receiving the key.
    # Thus we use retry_flag to delay the task retry until after attempting
    # to push to all apis.
    retry_flag = False
    for kps in dirty:
        if kps.api.name in ReplicatedApiNames:
            # Skip this API because we've queued a replicate_key task above
            print u"push_key for {k} ignoring {a} because it uses replicate_key.".format(k=key.key, a=kps.api.name)
            continue

        endpoint = urljoin(kps.api.url, endpoints[kps.status])
        try:
            apicall(endpoint, kps.api.signing_key, api=kps.api.name,
                    key=kps.key.key, email=kps.key.email, status=kps.key.status)
            print 'sent key {k} to {a}'.format(k=key.key, a=kps.api.name)

# Path: locksmith/common.py
# def enum(name, **enums):
#     def __iter__(self):
# def get_signature(params, signkey):
# def apicall(url, signkey, **params):
# def cache(seconds = 900):
#     def doCache(f):
#         def x(*args, **kwargs):
#     E = type(name or 'Enum', (), enums)
# API_OPERATING_STATUSES = (
#     (1, 'Normal'),
#     (2, 'Degraded Service'),
#     (3, 'Service Disruption'),
#     (4, 'Undergoing Maintenance')
# )
# API_STATUSES = enum('ApiStatuses',
#                     Stealth=0,
#                     Active=1,
#                     Deprecated=2,
#                     Disabled=3)
# KEY_STATUSES = (
#     ('U', 'Unactivated'),
#     ('A', 'Active'),
#     ('S', 'Suspended')
# )
# UNPUBLISHED, PUBLISHED, NEEDS_UPDATE = range(3)
# PUB_STATUSES = (
#     (UNPUBLISHED, 'Unpublished'),
#     (PUBLISHED, 'Published'),
#     (NEEDS_UPDATE, 'Needs Update'),
# )


# Path: locksmith/hub/tasks.py
import urllib2
from urlparse import urljoin
from locksmith.common import apicall, UNPUBLISHED, PUBLISHED, NEEDS_UPDATE
from celery.task import task
from django.conf import settings


@task(max_retries=5)
def push_key(key, replicate_too=True):
    if replicate_too:
        for kps in key.pub_statuses.filter(api__push_enabled=True):
            if kps.api.name in ReplicatedApiNames:
                replicate_key.delay(key, kps.api)

    endpoints = {UNPUBLISHED: 'create_key/', NEEDS_UPDATE: 'update_key/'}
    dirty = key.pub_statuses.exclude(status=PUBLISHED).filter(
              api__push_enabled=True).select_related()
    if not dirty:
        print u"Skipping push_key for {k} because all KeyPublicationStatus objects are PUBLISHED.".format(k=key.key)

    # Retrying immediately on failure would allow a broken or unresponsive
    # api to prevent other, properly functioning apis from receiving the key.
    # Thus we use retry_flag to delay the task retry until after attempting
    # to push to all apis.
    retry_flag = False
    for kps in dirty:
        if kps.api.name in ReplicatedApiNames:
            # Skip this API because we've queued a replicate_key task above
            print u"push_key for {k} ignoring {a} because it uses replicate_key.".format(k=key.key, a=kps.api.name)
            continue

        endpoint = urljoin(kps.api.url, endpoints[kps.status])
        try:
            apicall(endpoint, kps.api.signing_key, api=kps.api.name,
                    key=kps.key.key, email=kps.key.email, status=kps.key.status)
            print 'sent key {k} to {a}'.format(k=key.key, a=kps.api.name)

            kps.status = PUBLISHED