<commit_before># -*- coding: utf-8 -*-

# Akvo RSR is covered by the GNU Affero General Public License.
# See more details in the license.txt file located at the root folder of the Akvo RSR module.
# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.

import collections

from ....rsr.models.custom_field import ProjectCustomField
from ....rsr.models.project import Project

from .. import ImportMapper, akvo_ns

# project editor sections with text fields
# TODO: fix this; there should exist one place where the sections are defined
SECTION_ONE = 1
SECTION_FOUR = 4

TextFieldInfo = collections.namedtuple(
        'TextFieldInfo',
        ['akvo_type', 'order', 'cf_section']
)

project_text_fields = {
    'title': TextFieldInfo(akvo_type=None, order=None, cf_section=SECTION_ONE),
    'subtitle': TextFieldInfo(akvo_type=4, order=None, cf_section=SECTION_ONE),
    'project_plan_summary': TextFieldInfo(akvo_type=5, order=1, cf_section=SECTION_FOUR),
    'goals_overview': TextFieldInfo(akvo_type=8, order=None, cf_section=SECTION_FOUR),
    'background': TextFieldInfo(akvo_type=6, order=2, cf_section=SECTION_FOUR),
    'current_status': TextFieldInfo(akvo_type=9, order=3, cf_section=SECTION_FOUR),
    'target_group': TextFieldInfo(akvo_type=3, order=None, cf_section=SECTION_FOUR),
    'project_plan': TextFieldInfo(akvo_type=7, order=4, cf_section=None),
    'sustainability': TextFieldInfo(akvo_type=10, order=5, cf_section=None),
}


class Descriptions(ImportMapper):

    def __init__(self, iati_import_job, parent_elem, project, globals,
                 related_obj=None):
        super(Descriptions, self).__init__(
                iati_import_job, parent_elem, project, globals)
        self.model = Project

    def find_description_by_akvo_type(self, field):
        type = project_text_fields[field].akvo_type
        if type:
            return self.parent_elem.find(
                    "description[@{}='{}']".format(akvo_ns('type'), type))

    def find_description_by_order(self, field):
        """
        Helper method for finding the Nth description field where N is the order param
        :param order: the description field ordinal
        :return: the description element or None if there is no element that matches
        """
        order = project_text_fields[field].order
        if order:
            count = 0
            for description in self.parent_elem.findall("description"):
                description_text = self.get_text(description)
                if (not 'type' in description.attrib.keys() or description.attrib['type'] == '1') \
                        and (not akvo_ns('type') in description.attrib.keys()):
                    count += 1
                    if count == order:
                        return description
        return None

    def do_import(self):
        project = self.project
        changes = []

        for field in project_text_fields.keys():
            text = ''
            # try to find the text by akvo type
            element = self.find_description_by_akvo_type(field)
            # then do any special handling if available
            if element is None:

                custom_method = getattr(self, "get_{}".format(field), None)
                if custom_method:
                    element, text = custom_method()
                else:
                    # last chance, find by iati type or order of description field
                    element = self.find_description_by_order(field)
            if element is not None:
                if not text:
                    text = self.get_text(element)
                new_value = self.check_text_length_and_set_custom_field(
                    element, text, field, project_text_fields[field].cf_section)
                # is the currently saved value different from the newly found one?
                if getattr(project, field) != new_value:
                    setattr(project, field, new_value)
                    changes.append(field)
                    project.save(update_fields=changes)
        return changes


    def get_title(self):
        # title
        element = self.parent_elem.find('title')
        if element is not None:
            return element, self.get_text(element)
        return None, ''

    def get_subtitle(self):
        return self.get_title()

    def get_goals_overview(self):
        element = self.get_child_element_text(
                self.parent_elem, "description[<EMAIL>='2']", 'goals_overview')
        if element is None:
            text = '\n'.join(
                ["- {}".format(
                    self.get_text(title)
                ) for title in self.parent_elem.findall('result/title')]
            )
            return self.parent_elem.findall('result/title'), text
        return None, ''

    def get_target_group(self):
        text, element = self.get_child_element_text(
                self.parent_elem, "description[@<EMAIL>='3']", 'target_group', return_element=True)
        return element, text


class CustomFields(ImportMapper):

    def __init__(self, iati_import_job, parent_elem, project, globals,
                 related_obj=None):
        super(CustomFields, self).__init__(iati_import_job, parent_elem,
                                           project, globals, related_obj)
        self.model = ProjectCustomField

    def do_import(self):
        """<commit_msg>[#1828] Fix goals overview from result titles<commit_after># -*- coding: utf-8 -*-

# Akvo RSR is covered by the GNU Affero General Public License.
# See more details in the license.txt file located at the root folder of the Akvo RSR module.
# For additional details on the GNU license please see < http://www.gnu.org/licenses/agpl.html >.

import collections

from ....rsr.models.custom_field import ProjectCustomField
from ....rsr.models.project import Project

from .. import ImportMapper, akvo_ns

# project editor sections with text fields
# TODO: fix this; there should exist one place where the sections are defined
SECTION_ONE = 1
SECTION_FOUR = 4

TextFieldInfo = collections.namedtuple(
        'TextFieldInfo',
        ['akvo_type', 'order', 'cf_section']
)

project_text_fields = {
    'title': TextFieldInfo(akvo_type=None, order=None, cf_section=SECTION_ONE),
    'subtitle': TextFieldInfo(akvo_type=4, order=None, cf_section=SECTION_ONE),
    'project_plan_summary': TextFieldInfo(akvo_type=5, order=1, cf_section=SECTION_FOUR),
    'goals_overview': TextFieldInfo(akvo_type=8, order=None, cf_section=SECTION_FOUR),
    'background': TextFieldInfo(akvo_type=6, order=2, cf_section=SECTION_FOUR),
    'current_status': TextFieldInfo(akvo_type=9, order=3, cf_section=SECTION_FOUR),
    'target_group': TextFieldInfo(akvo_type=3, order=None, cf_section=SECTION_FOUR),
    'project_plan': TextFieldInfo(akvo_type=7, order=4, cf_section=None),
    'sustainability': TextFieldInfo(akvo_type=10, order=5, cf_section=None),
}


class Descriptions(ImportMapper):

    def __init__(self, iati_import_job, parent_elem, project, globals,
                 related_obj=None):
        super(Descriptions, self).__init__(
                iati_import_job, parent_elem, project, globals)
        self.model = Project

    def find_description_by_akvo_type(self, field):
        type = project_text_fields[field].akvo_type
        if type:
            return self.parent_elem.find(
                    "description[@{}='{}']".format(akvo_ns('type'), type))

    def find_description_by_order(self, field):
        """
        Helper method for finding the Nth description field where N is the order param
        :param order: the description field ordinal
        :return: the description element or None if there is no element that matches
        """
        order = project_text_fields[field].order
        if order:
            count = 0
            for description in self.parent_elem.findall("description"):
                description_text = self.get_text(description)
                if (not 'type' in description.attrib.keys() or description.attrib['type'] == '1') \
                        and (not akvo_ns('type') in description.attrib.keys()):
                    count += 1
                    if count == order:
                        return description
        return None

    def do_import(self):
        project = self.project
        changes = []

        for field in project_text_fields.keys():
            text = ''
            # try to find the text by akvo type
            element = self.find_description_by_akvo_type(field)
            # then do any special handling if available
            if element is None:
                custom_method = getattr(self, "get_{}".format(field), None)
                if custom_method:
                    element, text = custom_method()
                else:
                    # last chance, find by iati type or order of description field
                    element = self.find_description_by_order(field)
            if element is not None:
                if not text:
                    text = self.get_text(element)
                new_value = self.check_text_length_and_set_custom_field(
                    element, text, field, project_text_fields[field].cf_section)
                # is the currently saved value different from the newly found one?
                if getattr(project, field) != new_value:
                    setattr(project, field, new_value)
                    changes.append(field)
                    project.save(update_fields=changes)
        return changes

    def get_title(self):
        # title
        element = self.parent_elem.find('title')
        if element is not None:
            return element, self.get_text(element)
        return None, ''

    def get_subtitle(self):
        return self.get_title()

    def get_goals_overview(self):
        text, element = self.get_child_element_text(
                self.parent_elem, "description[@type='2']", 'goals_overview', return_element=True)
        if element is None:
            text = '\n'.join(
                ["- {}".format(
                    self.get_text(title)
                ) for title in self.parent_elem.findall('result/title')]
            )
            return self.parent_elem.find('result/title'), text
        return element, text

    def get_target_group(self):
        text, element = self.get_child_element_text(
                self.parent_elem, "description[@type='3']", 'target_group', return_element=True)
        return element, text


class CustomFields(ImportMapper):

    def __init__(self, iati_import_job, parent_elem, project, globals,
                 related_obj=None):
        super(CustomFields, self).__init__(iati_import_job, parent_elem,
                                           project, globals, related_obj)
        self.model = ProjectCustomField

    def do_import(self):
        """
{'fraction_non_alphanumeric': 0.09377859103385179, 'fraction_numerical': 0.004391582799634035, 'mean_word_length': 2.385258593991948, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 7, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4140116', 'n_tokens_mistral': 3095, 'n_tokens_neox': 2986, 'n_words': 779}