# 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 os

import pytest
import xmlschema

from passerelle.contrib.utils.axel import AxelSchema

XSD_BASE_DIR = os.path.join(
    os.path.dirname(os.path.abspath(__file__)), '../passerelle/contrib/toulouse_axel/xsd'
)


@pytest.mark.parametrize('date_type', ['DATEREQUIREDType', 'DATEType'])
def test_date_mapping(date_type):
    xsd = """<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
    <xsd:import schemaLocation="{path}/AllAxelTypes.xsd" namespace="urn:AllAxelTypes"  />
    <xsd:complexType name="PORTAILType">
        <xsd:sequence>
            <xsd:element name="DATE" type="all:{date_type}"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="PORTAIL" type="PORTAILType"/>
</xsd:schema>""".format(
        path=XSD_BASE_DIR, date_type=date_type
    )

    schema = AxelSchema(xsd, 'PORTAIL')
    xml_data = schema.encode({'PORTAIL': {'DATE': '2019-12-12'}})
    assert xml_data.find('DATE').text == '12/12/2019'

    json_data = schema.decode(xml_data)
    assert json_data['DATE'] == '2019-12-12'

    with pytest.raises(xmlschema.XMLSchemaValidationError):
        xml_data = schema.encode({'PORTAIL': {'DATE': 'foobar'}})
        assert xml_data.find('DATE').text == 'foobar'
        schema.decode(xml_data)

    if date_type == 'DATEType':
        xml_data = schema.encode({'PORTAIL': {'DATE': ''}})
        assert xml_data.find('DATE').text == ''

        json_data = schema.decode(xml_data)
        assert json_data['DATE'] is None


@pytest.mark.parametrize('bool_type', ['OUINONREQUIREDType', 'OUINONType'])
@pytest.mark.parametrize(
    'value, expected, py_expected',
    [
        ('OUI', 'OUI', True),
        ('oui', 'OUI', True),
        ('Oui', 'OUI', True),
        ('TRUE', 'OUI', True),
        ('true', 'OUI', True),
        ('True', 'OUI', True),
        (True, 'OUI', True),
        ('1', 'OUI', True),
        ('NON', 'NON', False),
        ('non', 'NON', False),
        ('Non', 'NON', False),
        ('FALSE', 'NON', False),
        ('false', 'NON', False),
        ('False', 'NON', False),
        (False, 'NON', False),
        ('0', 'NON', False),
        ('FOOBAR', 'FOOBAR', None),
        ('42', '42', None),
        ('OUIFOOBAR', 'OUIFOOBAR', None),
        ('FOONONBAR', 'FOONONBAR', None),
    ],
)
def test_bool_mapping(bool_type, value, expected, py_expected):
    if expected == '' and bool_type == 'OUINONREQUIREDType':
        # required, can't be empty
        return

    xsd = """<?xml version="1.0" encoding="utf-8" ?>
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:all="urn:AllAxelTypes">
    <xsd:import schemaLocation="{path}/AllAxelTypes.xsd" namespace="urn:AllAxelTypes"  />
    <xsd:complexType name="PORTAILType">
        <xsd:sequence>
            <xsd:element name="BOOL" type="all:{bool_type}"/>
        </xsd:sequence>
    </xsd:complexType>
    <xsd:element name="PORTAIL" type="PORTAILType"/>
</xsd:schema>""".format(
        path=XSD_BASE_DIR, bool_type=bool_type
    )

    schema = AxelSchema(xsd, 'PORTAIL')

    if py_expected is None:
        with pytest.raises(xmlschema.XMLSchemaValidationError):
            xml_data = schema.encode({'PORTAIL': {'BOOL': value}})
            assert xml_data.find('BOOL').text == expected
            schema.decode(xml_data)
    else:
        xml_data = schema.encode({'PORTAIL': {'BOOL': value}})
        assert xml_data.find('BOOL').text == expected
        json_data = schema.decode(xml_data)
        assert json_data['BOOL'] is py_expected
