# Path: name/validators.py
# def validate_merged_with(name):
#     """Validator for the merged_with ForeignKey field.
# 
#     This will prevent two scenarios from occurring.
#     1. Merging with a nonexistent Name object.
# 
#     2. Creating a loop of foreign key relationships.
#         For example:
#             Name 1 -> Name 2 -> Name 3 -> Name 1
# 
#         We need to prevent this because navigating to a name that has
#         been merged with another, will redirect you to the Name it has
#         been merged with.  If a loop is created, we will also create
#         the opportunity for an HTTP redirect loop.
# 
#     Unlike typical Django validators, this requires a model instance
#     as a parameter, instead of the value, which in this case would have
#     been the ID of the related model.  Because of this requirement, this
#     validator cannot be added via the `validator` kwarg on a ForeignKey
#     field.  Rather this method should be called from the `clean` method.
#     """
#     # Return early if there is no need to validate.
#     if name.merged_with is None:
#         return
# 
#     # Get the Name class from the model instance, to avoid
#     # circular importing name.models.Name.
#     Name = name.__class__
# 
#     # Prevent the user from attempting to merge with a nonexistent
#     # Name.
#     try:
#         merge_target = Name.objects.get(id=name.merged_with_id)
#     except Name.DoesNotExist:
#         raise ValidationError(
#             dict(merged_with='The merge target must exist.'))
# 
#     # Prevent the user from attempting to merge a name with itself.
#     if name.merged_with_id == name.id:
#         raise ValidationError(
#             dict(merged_with='Unable to merge a Name with itself.'))
# 
#     # Iterate through the generator and keep track of the return names.
#     # We will find a loop if the return name is already in
#     # merged_list. If this happens we will raise a validation error.
#     # If we don't find duplicates, then no loop has been created and
#     # the generator will raise it's own StopIteration and we will
#     # implicitly return.
#     merge_sequence = [name]
#     for name in follow_merged_with(merge_target):
#         if name in merge_sequence:
#             msg = ('The specified merge action completes a merge loop. '
#                    'Unable to complete merge.')
#             raise ValidationError(dict(merged_with=msg))
#         merge_sequence.append(name)


import json
import markdown2
from datetime import datetime
from itertools import groupby
from django.urls import reverse
from django.db import models, transaction
from django.utils import timezone
from django.utils.six.moves.urllib.parse import quote
from django.utils.six.moves.urllib.request import urlopen
from pynaco.naco import normalizeSimplified
from .validators import validate_merged_with
        """
        URL_RESOURCE = 'http://maps.googleapis.com/maps/api/geocode/json'
        URL_QUERY_TEMPLATE = '?address={address}&sensor=true'
        URL = URL_RESOURCE + URL_QUERY_TEMPLATE

        url = URL.format(address=quote(self.normalized_name))
        payload = json.load(urlopen(url))

        # Only add the location if the Name matched one and only one
        # location from the API.
        if payload.get('status') == "OK" and len(payload.get('results')) == 1:
            coordinate = payload['results'][0]['geometry']['location']
            self.location_set.create(latitude=coordinate['lat'],
                                     longitude=coordinate['lng'])

    def __assign_name_id(self):
        """Use the BaseTicketing object to assign a name_id."""
        if not self.name_id:
            self.name_id = str(BaseTicketing.objects.create())

    def save(self, **kwargs):
        self.__normalize_name()
        self.__assign_name_id()
        super(Name, self).save()
        if self.is_building() and not self.location_set.count():
            self.__find_location()

    def clean(self, *args, **kwargs):
        # Call merged_with_validator here so that we can pass in
        # the model instance.

# Path: name/validators.py
# def validate_merged_with(name):
#     """Validator for the merged_with ForeignKey field.
# 
#     This will prevent two scenarios from occurring.
#     1. Merging with a nonexistent Name object.
# 
#     2. Creating a loop of foreign key relationships.
#         For example:
#             Name 1 -> Name 2 -> Name 3 -> Name 1
# 
#         We need to prevent this because navigating to a name that has
#         been merged with another, will redirect you to the Name it has
#         been merged with.  If a loop is created, we will also create
#         the opportunity for an HTTP redirect loop.
# 
#     Unlike typical Django validators, this requires a model instance
#     as a parameter, instead of the value, which in this case would have
#     been the ID of the related model.  Because of this requirement, this
#     validator cannot be added via the `validator` kwarg on a ForeignKey
#     field.  Rather this method should be called from the `clean` method.
#     """
#     # Return early if there is no need to validate.
#     if name.merged_with is None:
#         return
# 
#     # Get the Name class from the model instance, to avoid
#     # circular importing name.models.Name.
#     Name = name.__class__
# 
#     # Prevent the user from attempting to merge with a nonexistent
#     # Name.
#     try:
#         merge_target = Name.objects.get(id=name.merged_with_id)
#     except Name.DoesNotExist:
#         raise ValidationError(
#             dict(merged_with='The merge target must exist.'))
# 
#     # Prevent the user from attempting to merge a name with itself.
#     if name.merged_with_id == name.id:
#         raise ValidationError(
#             dict(merged_with='Unable to merge a Name with itself.'))
# 
#     # Iterate through the generator and keep track of the return names.
#     # We will find a loop if the return name is already in
#     # merged_list. If this happens we will raise a validation error.
#     # If we don't find duplicates, then no loop has been created and
#     # the generator will raise it's own StopIteration and we will
#     # implicitly return.
#     merge_sequence = [name]
#     for name in follow_merged_with(merge_target):
#         if name in merge_sequence:
#             msg = ('The specified merge action completes a merge loop. '
#                    'Unable to complete merge.')
#             raise ValidationError(dict(merged_with=msg))
#         merge_sequence.append(name)


# Path: name/models.py
import json
import markdown2
from datetime import datetime
from itertools import groupby
from django.urls import reverse
from django.db import models, transaction
from django.utils import timezone
from django.utils.six.moves.urllib.parse import quote
from django.utils.six.moves.urllib.request import urlopen
from pynaco.naco import normalizeSimplified
from .validators import validate_merged_with

        """
        URL_RESOURCE = 'http://maps.googleapis.com/maps/api/geocode/json'
        URL_QUERY_TEMPLATE = '?address={address}&sensor=true'
        URL = URL_RESOURCE + URL_QUERY_TEMPLATE

        url = URL.format(address=quote(self.normalized_name))
        payload = json.load(urlopen(url))

        # Only add the location if the Name matched one and only one
        # location from the API.
        if payload.get('status') == "OK" and len(payload.get('results')) == 1:
            coordinate = payload['results'][0]['geometry']['location']
            self.location_set.create(latitude=coordinate['lat'],
                                     longitude=coordinate['lng'])

    def __assign_name_id(self):
        """Use the BaseTicketing object to assign a name_id."""
        if not self.name_id:
            self.name_id = str(BaseTicketing.objects.create())

    def save(self, **kwargs):
        self.__normalize_name()
        self.__assign_name_id()
        super(Name, self).save()
        if self.is_building() and not self.location_set.count():
            self.__find_location()

    def clean(self, *args, **kwargs):
        # Call merged_with_validator here so that we can pass in
        # the model instance.

        validate_merged_with(self)