# Passerelle - uniform access to data and services
# Copyright (C) 2015  Entr'ouvert
#
# This program is free software: you can redistribute it and/or modify it
# under the terms of the GNU Affero General Public License as published
# by the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU Affero General Public License for more details.
#
# You should have received a copy of the GNU Affero General Public License
# along with this program.  If not, see <http://www.gnu.org/licenses/>.


CONCILIATION_INDIVIDU = {
    'block': {'name': 'Individu', 'pk': "PK/IndexIndividu/@V"},
    'criteria': {
        5: (
            {
                'EtatCivil/Nom/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
                'EtatCivil/DateNaissance/@V': 'equal',
            },
            {
                'EtatCivil/NomJeuneFille/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
                'EtatCivil/DateNaissance/@V': 'equal',
            },
        ),
        4: (
            {
                'EtatCivil/Nom/@V': 'equal',
                'EtatCivil/DateNaissance/@V': 'equal',
            },
            {
                'EtatCivil/NomJeuneFille/@V': 'equal',
                'EtatCivil/DateNaissance/@V': 'equal',
            },
            {
                'EtatCivil/Nom/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
            },
            {
                'EtatCivil/NomJeuneFille/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
            },
        ),
    },
    'input': {
        'EtatCivil/Nom/@V': 'nom',
        'EtatCivil/Prenom/@V': 'prenom',
        'EtatCivil/DateNaissance/@V': 'dn',
        'EtatCivil/NomJeuneFille/@V': 'nom',
    },
    'output': [
        "Dossier/PK/IndexDossier/@V",
        "PK/IndexIndividu/@V",
        "EtatCivil/Nom/@V",
        "EtatCivil/NomJeuneFille/@V",
        "EtatCivil/Prenom/@V",
        "EtatCivil/DateNaissance/@V",
        "Dossier/Adresse/NumeroLieu/@V",
        "Dossier/Adresse/NatureLieu/@Lc",
        "Dossier/Adresse/NomLieu/@V",
        "Dossier/Adresse/ComplementLieu/@V",
        "Dossier/Adresse/CpLieu/@V",
        "Dossier/Adresse/Commune/NomCom/@V",
    ],
}

CONCILIATION_INDIVIDU_SANS_DN = {
    'block': {'name': 'Individu', 'pk': "PK/IndexIndividu/@V"},
    'criteria': {
        5: (
            {
                'EtatCivil/Nom/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
            },
            {
                'EtatCivil/NomJeuneFille/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
            },
        ),
        4: (
            {
                'EtatCivil/Nom/@V': 'equal',
                'EtatCivil/Prenom/@V': 'approx',
            },
        ),
        3: (
            {
                'EtatCivil/Nom/@V': 'approx',
                'EtatCivil/Prenom/@V': 'equal',
            },
        ),
    },
    'input': {
        'EtatCivil/Nom/@V': 'nom',
        'EtatCivil/Prenom/@V': 'prenom',
        'EtatCivil/NomJeuneFille/@V': 'nom',
    },
    'output': [
        "Dossier/PK/IndexDossier/@V",
        "PK/IndexIndividu/@V",
        "EtatCivil/Nom/@V",
        "EtatCivil/NomJeuneFille/@V",
        "EtatCivil/Prenom/@V",
        "EtatCivil/DateNaissance/@V",
        "Dossier/Adresse/NumeroLieu/@V",
        "Dossier/Adresse/NatureLieu/@Lc",
        "Dossier/Adresse/NomLieu/@V",
        "Dossier/Adresse/ComplementLieu/@V",
        "Dossier/Adresse/CpLieu/@V",
        "Dossier/Adresse/Commune/NomCom/@V",
    ],
}

CONCILIATION_ADRESSE = {
    'block': {'name': 'Adresse', 'pk': "CodeLieu/@V"},
    'criteria': {
        5: (
            {
                'NomLieu/@V': 'matches',
                'Commune/PK/CodeDepartement/@V': 'equal',
                'Commune/PK/CodeCommune/@V': 'equal',
            },
        ),
    },
    'input': {
        'NomLieu/@V': 'lieu',
        'Commune/PK/CodeDepartement/@V': 'departement',
        'Commune/PK/CodeCommune/@V': 'commune',
    },
    'output': [
        "CodeLieu/@V",
        "NatureLieu/@Lc",
        "NomLieu/@V",
        "CodePostal/@V",
        "Commune/PK/CodeCommune/@V",
        "Commune/NomCom/@V",
        "CodeDepartement/@V",
    ],
}

CONCILIATION_PARTICULIER = {
    'block': {'name': 'Particulier', 'pk': "PK/IndexParticulier/@V"},
    'criteria': {
        5: (
            {
                'EtatCivil/Nom/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
            },
            {
                'EtatCivil/NomJeuneFille/@V': 'equal',
                'EtatCivil/Prenom/@V': 'equal',
            },
        ),
        4: (
            {
                'EtatCivil/Nom/@V': 'equal',
                'EtatCivil/Prenom/@V': 'approx',
            },
        ),
        3: (
            {
                'EtatCivil/Nom/@V': 'approx',
                'EtatCivil/Prenom/@V': 'equal',
            },
        ),
    },
    'input': {
        'EtatCivil/Nom/@V': 'nom',
        'EtatCivil/Prenom/@V': 'prenom',
        'EtatCivil/NomJeuneFille/@V': 'nom',
    },
    'output': [
        "PK/IndexParticulier/@V",
        "EtatCivil/Nom/@V",
        "EtatCivil/NomJeuneFille/@V",
        "EtatCivil/Prenom/@V",
        "EtatCivil/DateNaissance/@V",
        "Adresse/NumeroLieu/@V",
        "Adresse/NatureLieu/@Lc",
        "Adresse/NomLieu/@V",
        "Adresse/ComplementLieu/@V",
        "Adresse/CpLieu/@V",
        "Adresse/Commune/NomCom/@V",
    ],
}


def conciliation_payload(config, **data):
    block = {"name": config['block']['name'], "PrimaryKey": {"key": [config['block']['pk']]}}
    setting = []
    for affinity, afflist in config['criteria'].items():
        for aff in afflist:
            criterium = []
            for xpath, op in aff.items():
                criterium.append({'key': xpath, 'operator': op})
            setting.append(
                {
                    "affinity": affinity,
                    "Criterium": criterium,
                }
            )
    criterium = []
    for xpath, local in config['input'].items():
        criterium.append({'key': xpath, 'value': data.get(local, '')})
    returndata = []
    for xpath in config['output']:
        returndata.append(xpath)

    return {
        "ConciliationInputWS": {
            "Block": block,
            "Input": {
                "Settings": {
                    "Setting": setting,
                },
                "Criteria": {"Criterium": criterium},
            },
            "Output": {
                "ReturnDatas": {"returnData": returndata},
            },
        }
    }


def conciliation_output2dict(config, entity):
    d = {}
    for xpath in config['output']:
        x = entity
        for k in xpath.split('/'):
            x = x.get(k, {})
        d[xpath] = x or ''
    return d
