# Path: lib/phantom_on_the_capitol.py
# class PhantomOfTheCapitol():
# 
#     def __init__(self, endpoint, opts=None):
#         self.endpoint = endpoint
#         self.opts = opts
# 
#     def retrieve_form_elements(self, args):
#         """
#         Obtain the steps needed to fill out the congressial webform of provided args
# 
#         @param args: [List<String>|Message]
#         @return: [Dictionary|None]
#         """
#         bioguide_ids = args if type(args) is list else [x.bioguide_id for x in args.get_legislators()]
#         try:
#             steps = requests.post(self.endpoint + '/retrieve-form-elements',
#                                   headers={"Content-Type": 'application/json'},
#                                   data=json.dumps({'bio_ids': bioguide_ids}))
# 
#             return steps.json()
#         except:
#             print('Failed to obtain steps.')
#             return None
# 
#     def fill_out_form(self, json_dict):
#         """
#         Attempts to fill out the congressional webform with input json data.
# 
#         @param json_dict: dictionary to be converted into a json string. Example of input schema:
#                           {"bio_id": "A000000",
#                            "fields": {
#                                 "$NAME_FIRST": "John",
#                                 "$NAME_LAST": "Doe",
#                                 "$ADDRESS_STREET": "123 Main Street",
#                                 "$ADDRESS_CITY": "New York",
#                                 "$ADDRESS_ZIP5": "10112",
#                                 "$EMAIL": "joe@example.com",
#                                 "$MESSAGE": "I have concerns about the proposal....",
#                                 "$NAME_PREFIX": "Grand Moff"
#                                 }
#                           }
#         @type json_dict: dict
#         @return: dictionary of success or failure
#         @rtype: dict
#         """
#         try:
#             r = requests.post(self.endpoint + '/fill-out-form',
#                               headers={"Content-Type": 'application/json'},
#                               data=json.dumps(json_dict))
# 
#             return r.json()
#         except:
#             print('Failed to execute API call to phantom of the capitol.')
#             # TODO log errors
#             return None
# 
# Path: lib/usps.py
# CODE_TO_STATE = dict(USPS_CHOICES)
#     USPS_BASE_URL = 'https://tools.usps.com/go/ZipLookupResultsAction!input.action'
# class USPSScraper:
#     def usps_request(**kwargs):
#     def usps_address_lookup(queue=None, **kwargs):
#     def usps_zip_lookup(street_address, city, state, z5=''):
# 
# Path: services/determine_district_service.py
# def determine_district(**kwargs):
# 
# Path: services/geolocation_service.py
# def geolocate(**kwargs):
# def reverse_geolocate(lat, lng, state=''):
# 
# Path: services/address_inferrence_service.py
# def address_lookup(**kwargs):
# def zip4_lookup(street_address, city, state, zip5=''):
# 
# Path: emailcongress/utils.py
# def bool_eval(v):
# def ordinal(n):
# def construct_link(protocol, hostname, path, get_param_dict=None):
# 
# Path: emailcongress/celery.py
# @celery.task(bind=True, max_retries=celery.conf.MAX_RETRIES, default_retry_delay=celery.conf.RETRY_DELAY)
# def send_to_phantom_of_the_capitol(self, msg_id=None, msgleg_id=None, force=False):
#     """
# 
#     @param self:
#     @type self:
#     @param msg_id:
#     @type msg_id:
#     @param msgleg_id:
#     @type msgleg_id:
#     @param force:
#     @type force:
#     @return:
#     @rtype:
#     """
#     if settings.CONFIG_DICT['email']['submit_to_webform'] or force:
#         try:
#             from emailcongress.models import Message, MessageLegislator
#             if msgleg_id is not None:
#                 MessageLegislator.objects.get(id=msgleg_id).send()
#             elif msg_id is not None:
#                 msg = Message.objects.get(pk=msg_id)
#                 msg.send()
#                 if msg.get_send_status() == 'sent' or self.request.retries >= self.max_retries:
#                     emailer.NoReply(msg.user_message_info.user.django_user).send_status(msg.to_legislators, msg).send()
#                 else:
#                     raise self.retry(exc=Exception)
#         except:
#             raise Exception(traceback.format_exc())
#             # TODO robust error handling


import random
import uuid
from datetime import datetime, timedelta
from django.db import models
from django.db.models import Q
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core import serializers
from django.db.models.signals import post_save, pre_save, pre_delete, post_delete
from django.dispatch import receiver
from django.contrib.auth.models import User as DjangoUser
from django.core.urlresolvers import reverse
from django.conf import settings
from django.db import IntegrityError, transaction
from django.utils import timezone
from jsonfield import JSONField
from localflavor.us import models as us_models
from lib.phantom_on_the_capitol import PhantomOfTheCapitol
from lib import usps
from services import determine_district_service, geolocation_service, address_inferrence_service
from emailcongress import utils
from emailcongress.celery import send_to_phantom_of_the_capitol
    def __str__(self):
        return self.key

    @property
    def user(self):
        """
        Convenience method for getting the django auth user from this Token if it exists.

        @return: the django auth user or None
        @rtype: (DjangoUser|None)
        """
        if type(self.content_object) == User:
            return self.content_object.django_user
        else:
            return None

    def save(self, *args, **kwargs):
        """
        Generates a key if one doesn't exist before saving the token.
        """
        if not self.key:
            self.key = self.uid_creator()
        super().save(*args, **kwargs)

    def reset(self, key=None):
        self.key = key if key is not None else self.uid_creator()
        self.save()
        return self.key

    def link(self):

# Path: lib/phantom_on_the_capitol.py
# class PhantomOfTheCapitol():
# 
#     def __init__(self, endpoint, opts=None):
#         self.endpoint = endpoint
#         self.opts = opts
# 
#     def retrieve_form_elements(self, args):
#         """
#         Obtain the steps needed to fill out the congressial webform of provided args
# 
#         @param args: [List<String>|Message]
#         @return: [Dictionary|None]
#         """
#         bioguide_ids = args if type(args) is list else [x.bioguide_id for x in args.get_legislators()]
#         try:
#             steps = requests.post(self.endpoint + '/retrieve-form-elements',
#                                   headers={"Content-Type": 'application/json'},
#                                   data=json.dumps({'bio_ids': bioguide_ids}))
# 
#             return steps.json()
#         except:
#             print('Failed to obtain steps.')
#             return None
# 
#     def fill_out_form(self, json_dict):
#         """
#         Attempts to fill out the congressional webform with input json data.
# 
#         @param json_dict: dictionary to be converted into a json string. Example of input schema:
#                           {"bio_id": "A000000",
#                            "fields": {
#                                 "$NAME_FIRST": "John",
#                                 "$NAME_LAST": "Doe",
#                                 "$ADDRESS_STREET": "123 Main Street",
#                                 "$ADDRESS_CITY": "New York",
#                                 "$ADDRESS_ZIP5": "10112",
#                                 "$EMAIL": "joe@example.com",
#                                 "$MESSAGE": "I have concerns about the proposal....",
#                                 "$NAME_PREFIX": "Grand Moff"
#                                 }
#                           }
#         @type json_dict: dict
#         @return: dictionary of success or failure
#         @rtype: dict
#         """
#         try:
#             r = requests.post(self.endpoint + '/fill-out-form',
#                               headers={"Content-Type": 'application/json'},
#                               data=json.dumps(json_dict))
# 
#             return r.json()
#         except:
#             print('Failed to execute API call to phantom of the capitol.')
#             # TODO log errors
#             return None
# 
# Path: lib/usps.py
# CODE_TO_STATE = dict(USPS_CHOICES)
#     USPS_BASE_URL = 'https://tools.usps.com/go/ZipLookupResultsAction!input.action'
# class USPSScraper:
#     def usps_request(**kwargs):
#     def usps_address_lookup(queue=None, **kwargs):
#     def usps_zip_lookup(street_address, city, state, z5=''):
# 
# Path: services/determine_district_service.py
# def determine_district(**kwargs):
# 
# Path: services/geolocation_service.py
# def geolocate(**kwargs):
# def reverse_geolocate(lat, lng, state=''):
# 
# Path: services/address_inferrence_service.py
# def address_lookup(**kwargs):
# def zip4_lookup(street_address, city, state, zip5=''):
# 
# Path: emailcongress/utils.py
# def bool_eval(v):
# def ordinal(n):
# def construct_link(protocol, hostname, path, get_param_dict=None):
# 
# Path: emailcongress/celery.py
# @celery.task(bind=True, max_retries=celery.conf.MAX_RETRIES, default_retry_delay=celery.conf.RETRY_DELAY)
# def send_to_phantom_of_the_capitol(self, msg_id=None, msgleg_id=None, force=False):
#     """
# 
#     @param self:
#     @type self:
#     @param msg_id:
#     @type msg_id:
#     @param msgleg_id:
#     @type msgleg_id:
#     @param force:
#     @type force:
#     @return:
#     @rtype:
#     """
#     if settings.CONFIG_DICT['email']['submit_to_webform'] or force:
#         try:
#             from emailcongress.models import Message, MessageLegislator
#             if msgleg_id is not None:
#                 MessageLegislator.objects.get(id=msgleg_id).send()
#             elif msg_id is not None:
#                 msg = Message.objects.get(pk=msg_id)
#                 msg.send()
#                 if msg.get_send_status() == 'sent' or self.request.retries >= self.max_retries:
#                     emailer.NoReply(msg.user_message_info.user.django_user).send_status(msg.to_legislators, msg).send()
#                 else:
#                     raise self.retry(exc=Exception)
#         except:
#             raise Exception(traceback.format_exc())
#             # TODO robust error handling


# Path: emailcongress/models.py
import random
import uuid
from datetime import datetime, timedelta
from django.db import models
from django.db.models import Q
from django.contrib.contenttypes.fields import GenericForeignKey, GenericRelation
from django.contrib.contenttypes.models import ContentType
from django.core import serializers
from django.db.models.signals import post_save, pre_save, pre_delete, post_delete
from django.dispatch import receiver
from django.contrib.auth.models import User as DjangoUser
from django.core.urlresolvers import reverse
from django.conf import settings
from django.db import IntegrityError, transaction
from django.utils import timezone
from jsonfield import JSONField
from localflavor.us import models as us_models
from lib.phantom_on_the_capitol import PhantomOfTheCapitol
from lib import usps
from services import determine_district_service, geolocation_service, address_inferrence_service
from emailcongress import utils
from emailcongress.celery import send_to_phantom_of_the_capitol

    def __str__(self):
        return self.key

    @property
    def user(self):
        """
        Convenience method for getting the django auth user from this Token if it exists.

        @return: the django auth user or None
        @rtype: (DjangoUser|None)
        """
        if type(self.content_object) == User:
            return self.content_object.django_user
        else:
            return None

    def save(self, *args, **kwargs):
        """
        Generates a key if one doesn't exist before saving the token.
        """
        if not self.key:
            self.key = self.uid_creator()
        super().save(*args, **kwargs)

    def reset(self, key=None):
        self.key = key if key is not None else self.uid_creator()
        self.save()
        return self.key

    def link(self):

        return utils.construct_link(settings.PROTOCOL,