

class ChangeParser():
    """
    Provides many different notification change parsers and utility methods.
    """

    @staticmethod
    def get_changed_field_handler(top_level_type, field):
        """
        Returns a change handler for the field and top level object type. If
        not found then None is returned.

        :param top_level_type: The top level object type.
        :type message: str
        :param field: The field name.
        :type message: str
        :returns: function: Returns a change field handler, None if not found
        """

        specific_mapped_type = __specific_field_to_change_handler__.get(top_level_type)

        # Check for a specific mapped field first, if there isn't one
        # then just try to use the general mapped fields.
        if specific_mapped_type is not None:
            specific_mapped_handler = specific_mapped_type.get(field)

            if specific_mapped_handler is not None:
                return specific_mapped_handler

        return __general_field_to_change_handler__.get(field)


    ############################################################################
    # Generic change parsers
    ############################################################################
    @staticmethod
    def flatten_objects_to_list(objects, key):
        """
        Flattens an object list to list values from the input key.

        :type objects: list of complex objects
        :param objects: list(object).
        :type key: The name of the field/key to extract for the flattened list
        :param key: str
        :returns: str: Returns a list of extracted keys.
        """

        return_list = []

        for object in objects:
            return_list.append(object[key])

        return return_list

    @staticmethod
    def generic_child_fields_change_handler(old_value, new_value, fields, base_fqn=None):
        """
        Handles processing of changed fields where the input is a dictionary of
        values. This will only process the immediate children.

        :type old_value: The old mongo object to compare values against.
        :param old_value: A Mongo Document
        :type new_value: The updated/new mongo object to compare values against.
        :param new_value: A Mongo Document
        :type fields: list of field names to compare against
        :param fields: list(str).
        :type base_fqn: The base descriptor of the object
        :param base_fqn: str
        :returns: str: Returns a message summarizing the changes.
        """

        message = ""

        for field in fields:
            old_field_value = ""
            new_field_value = ""

            if old_value is not None:
                old_field_value = old_value[field]

            if new_value is not None:
                new_field_value = new_value[field]

            if old_field_value != new_field_value:
                change_message = ChangeParser.generic_single_field_change_handler(
                        old_field_value, new_field_value, field, base_fqn)
                message += change_message[:1].capitalize() + change_message[1:]

        return message

    @staticmethod
    def generic_list_change_handler(old_value, new_value, changed_field):
        """
        Handles the processing of changed fields where the changed field
        is a list of items. Displays the changed value in unicode format.

        :type old_value: The old mongo object to compare values against.
        :param old_value: A Mongo Document
        :type new_value: The updated/new mongo object to compare values against.
        :param new_value: A Mongo Document
        :type changed_field: The field name that the comparisons will be against.
        :param changed_field: str
        :returns: str: Returns a message summarizing the changes.
        """

        removed_names = [x for x in old_value if x not in new_value and x != '']
        added_names = [x for x in new_value if x not in old_value and x != '']

        message = ""
        if len(added_names) > 0:
            message += "Added to %s: %s. " % (changed_field, unicode(', '.join(added_names)))