# passerelle - uniform access to multiple data sources and services
# Copyright (C) 2019 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/>.

import xml.etree.ElementTree as ET
from collections import OrderedDict
from decimal import Decimal

import jsonschema
import xmlschema

from passerelle.utils.json import flatten, flatten_json_schema, unflatten
from passerelle.utils.xml import JSONSchemaFromXMLSchema, text_content, to_json


def test_text_content():
    root = ET.fromstring('<root>aa<b>bb</b>cc</root>')
    assert text_content(root) == 'aabbcc'


def test_to_json():
    root = ET.fromstring(
        '''<root>
        <text1>1</text1>
        <text2>2</text2>
        <enfants>
            <enfant>
                <text3>3</text3>
            </enfant>
            <enfant>
                <text3>4</text3>
            </enfant>
            <zob/>
        </enfants>
        <zob/>
</root>'''
    )
    assert to_json(root) == {
        'text1': '1',
        'text2': '2',
        'enfants': [
            {'text3': '3'},
            {'text3': '4'},
        ],
    }


def test_xmlschema_to_jsonschema():
    schema_path = 'tests/exemple.xsd'

    # go from XML to JSON,
    # convert XMLSchema to JSONSchema
    # validate jsonschema, on converted data,
    # flatten the JSON schema,
    # flatten the data,
    # validate flattened data with flatenned JSON schema
    # unflatten data
    # convert unflattened data to XML
    # convert XML to JSON
    # then compare to initially converted JSON data
    schema = xmlschema.XMLSchema(schema_path, converter=xmlschema.UnorderedConverter)
    json_schema = JSONSchemaFromXMLSchema(schema, 'PACS')
    d = schema.elements['PACS'].decode(ET.parse('tests/data/pacs-doc.xml').getroot())
    d = {'PACS': d}
    json_schema.validate(d)
    flattened_json_schema = flatten_json_schema(json_schema.json_schema)
    flattened_d = flatten(d)
    jsonschema.validate(instance=flattened_d, schema=flattened_json_schema)
    d2 = unflatten(d)
    json_schema.validate(d2)

    tree = schema.elements['PACS'].encode(d2['PACS'], converter=xmlschema.UnorderedConverter)
    d3 = schema.elements['PACS'].decode(tree)
    assert d == {'PACS': d3}

    assert json_schema.json_schema['properties']['PACS']['properties']['testSimpleContent'] == OrderedDict(
        [
            ('type', 'object'),
            (
                'properties',
                OrderedDict(
                    [
                        (
                            '$',
                            OrderedDict(
                                [('type', 'integer'), ('minimum', Decimal('0')), ('maximum', Decimal('1000'))]
                            ),
                        ),
                        ('attribute', {'type': 'string'}),
                    ]
                ),
            ),
        ]
    )
