# -*- coding: utf-8 -*-

import datetime

import pytest
import requests_mock
from geolink_formatter.entity import Document, File
from requests.auth import HTTPBasicAuth

from pyramid_oereb.contrib.sources.document import OEREBlexSource
from pyramid_oereb.lib.records.documents import DocumentRecord, LegalProvisionRecord
from pyramid_oereb.lib.records.office import OfficeRecord
from tests.mockrequest import MockParameter


@pytest.mark.parametrize('valid,cfg', [
    (True, {
        'host': 'http://oereblex.example.com',
        'language': 'de',
        'canton': 'BL'
    }),
    (False, {
        'language': 'de',
        'canton': 'BL'
    }),
    (False, {
        'host': 'http://oereblex.example.com',
        'language': 'german',
        'canton': 'BL'
    }),
    (False, {
        'host': 'http://oereblex.example.com',
        'language': 'de'
    })
])
def test_init(valid, cfg):
    if valid:
        assert isinstance(OEREBlexSource(**cfg), OEREBlexSource)
    else:
        with pytest.raises(AssertionError):
            OEREBlexSource(**cfg)


@pytest.mark.parametrize('key,language,result', [
    ('official_title', None, None),
    ('municipality', None, 'Liestal'),
    ('municipality', 'de', {'de': 'Liestal'})
])
def test_get_mapped_value(key, language, result):
    file_ = File('Test', '/api/attachments/1', 'main')
    document = Document(id='test', title='Test', category='main', doctype='decree', files=[file_],
                        enactment_date=datetime.date.today(), subtype='Liestal', authority='Office')
    source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL',
                            mapping={'municipality': 'subtype'})
    assert source._get_mapped_value(document, key, language=language) == result


@pytest.mark.parametrize('i,document', [
    (1, Document(
        id='doc1',
        title='Document 1',
        category='main',
        doctype='edict',
        authority='Office',
        files=[File('File 1', '/api/attachments/1', 'main')],
        enactment_date=datetime.date.today()
    )),
    (2, Document(
        id='doc2',
        title='Document 2',
        category='main',
        doctype='decree',
        authority='Office',
        files=[
            File('File 2', '/api/attachments/2', 'main'),
            File('File 3', '/api/attachments/3', 'additional')
        ],
        enactment_date=datetime.date.today()
    )),
    (3, Document(
        id='doc1',
        title='Document 1',
        category='main',
        doctype='invalid',
        authority='Office',
        files=[File('File 1', '/api/attachments/1', 'main')],
        enactment_date=datetime.date.today()
    )),
    (4, Document(
        id='doc1',
        title='Document 1',
        category='main',
        doctype='decree',
        authority='Office',
        files=[],
        enactment_date=datetime.date.today()
    ))
])
def test_get_document_records(i, document):
    language = 'de'
    source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL')
    references = [
        Document(
            id='ref',
            title='Reference',
            category='related',
            doctype='edict',
            authority='Office',
            files=[File('Reference file', '/api/attachments/4', 'main')],
            enactment_date=datetime.date.today()
        )
    ]

    if i == 3:
        with pytest.raises(TypeError):
            source._get_document_records(document, language, references)
    elif i == 4:
        assert source._get_document_records(document, language, references) == []
    else:
        records = source._get_document_records(document, language, references)
        assert len(records) == i
        for idx, record in enumerate(records):
            if i == 1:
                assert isinstance(record, DocumentRecord)
            elif i == 2:
                assert isinstance(record, LegalProvisionRecord)
            assert record.title == {'de': 'Document {0}'.format(i)}
            assert record.published_from == datetime.date.today()
            assert record.canton == 'BL'
            assert record.text_at_web == {'de': '/api/attachments/{fid}'.format(fid=i + idx)}
            assert len(record.references) == 1
            reference = record.references[0]
            assert isinstance(reference, DocumentRecord)
            assert reference.title == {'de': 'Reference'}
            assert reference.canton == 'BL'
            assert reference.text_at_web == {'de': '/api/attachments/4'}


def test_read():
    with requests_mock.mock() as m:
        with open('./tests/resources/geolink_v1.1.1.xml', 'rb') as f:
            m.get('http://oereblex.example.com/api/geolinks/100.xml', content=f.read())
        source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL')
        source.read(MockParameter(), 100)
        assert len(source.records) == 2
        document = source.records[0]
        assert isinstance(document, DocumentRecord)
        assert isinstance(document.responsible_office, OfficeRecord)
        assert document.responsible_office.name == {'de': 'Landeskanzlei'}
        assert document.canton == 'BL'
        assert document.text_at_web == {
            'de': 'http://oereblex.example.com/api/attachments/313'
        }
        assert len(document.references) == 5


def test_read_related_decree_as_main():
    with requests_mock.mock() as m:
        with open('./tests/resources/geolink_v1.1.1.xml', 'rb') as f:
            m.get('http://oereblex.example.com/api/geolinks/100.xml', content=f.read())
        source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL',
                                related_decree_as_main=True)
        source.read(MockParameter(), 100)
        assert len(source.records) == 3
        document = source.records[0]
        assert isinstance(document, DocumentRecord)
        assert isinstance(document.responsible_office, OfficeRecord)
        assert document.responsible_office.name == {'de': 'Landeskanzlei'}
        assert document.canton == 'BL'
        assert document.text_at_web == {
            'de': 'http://oereblex.example.com/api/attachments/313'
        }
        assert len(document.references) == 4


def test_read_with_version_in_url():
    with requests_mock.mock() as m:
        with open('./tests/resources/geolink_v1.1.1.xml', 'rb') as f:
            m.get('http://oereblex.example.com/api/1.1.1/geolinks/100.xml', content=f.read())
        source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL',
                                pass_version=True)
        source.read(MockParameter(), 100)
        assert len(source.records) == 2


def test_read_with_specified_version():
    with requests_mock.mock() as m:
        with open('./tests/resources/geolink_v1.0.0.xml', 'rb') as f:
            m.get('http://oereblex.example.com/api/1.0.0/geolinks/100.xml', content=f.read())
        source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL',
                                pass_version=True, version='1.0.0')
        source.read(MockParameter(), 100)
        assert len(source.records) == 2


def test_read_with_specified_language():
    with requests_mock.mock() as m:
        with open('./tests/resources/geolink_v1.1.1.xml', 'rb') as f:
            m.get('http://oereblex.example.com/api/geolinks/100.xml?locale=fr', content=f.read())
        source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL')
        params = MockParameter()
        params.set_language('fr')
        source.read(params, 100)
        assert len(source.records) == 2
        document = source.records[0]
        assert document.responsible_office.name == {'fr': 'Landeskanzlei'}
        assert document.text_at_web == {
            'fr': 'http://oereblex.example.com/api/attachments/313'
        }


def test_authentication():
    auth = {
        'username': 'test',
        'password': 'test'
    }
    source = OEREBlexSource(host='http://oereblex.example.com', language='de', canton='BL', auth=auth)
    assert isinstance(source._auth, HTTPBasicAuth)


def test_get_document_title():
    document = Document([], id='1', title='Test')
    result = {'de': 'Test'}
    assert OEREBlexSource._get_document_title(document, File(), 'de') == result

[((426, 765), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""valid,cfg"""', "[(True, {'host': 'http://oereblex.example.com', 'language': 'de', 'canton':\n    'BL'}), (False, {'language': 'de', 'canton': 'BL'}), (False, {'host':\n    'http://oereblex.example.com', 'language': 'german', 'canton': 'BL'}),\n    (False, {'host': 'http://oereblex.example.com', 'language': 'de'})]"], {}), "('valid,cfg', [(True, {'host':\n    'http://oereblex.example.com', 'language': 'de', 'canton': 'BL'}), (\n    False, {'language': 'de', 'canton': 'BL'}), (False, {'host':\n    'http://oereblex.example.com', 'language': 'german', 'canton': 'BL'}),\n    (False, {'host': 'http://oereblex.example.com', 'language': 'de'})])\n", (449, 765), False, 'import pytest\n'), ((1068, 1234), 'pytest.mark.parametrize', 'pytest.mark.parametrize', (['"""key,language,result"""', "[('official_title', None, None), ('municipality', None, 'Liestal'), (\n    'municipality', 'de', {'de': 'Liestal'})]"], {}), "('key,language,result', [('official_title', None,\n    None), ('municipality', None, 'Liestal'), ('municipality', 'de', {'de':\n    'Liestal'})])\n", (1091, 1234), False, 'import pytest\n'), ((1303, 1345), 'geolink_formatter.entity.File', 'File', (['"""Test"""', '"""/api/attachments/1"""', '"""main"""'], {}), "('Test', '/api/attachments/1', 'main')\n", (1307, 1345), False, 'from geolink_formatter.entity import Document, File\n'), ((1559, 1679), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""', 'mapping': "{'municipality': 'subtype'}"}), "(host='http://oereblex.example.com', language='de', canton=\n    'BL', mapping={'municipality': 'subtype'})\n", (1573, 1679), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((2983, 3061), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""'}), "(host='http://oereblex.example.com', language='de', canton='BL')\n", (2997, 3061), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((8067, 8161), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""', 'auth': 'auth'}), "(host='http://oereblex.example.com', language='de', canton=\n    'BL', auth=auth)\n", (8081, 8161), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((8256, 8290), 'geolink_formatter.entity.Document', 'Document', (['[]'], {'id': '"""1"""', 'title': '"""Test"""'}), "([], id='1', title='Test')\n", (8264, 8290), False, 'from geolink_formatter.entity import Document, File\n'), ((4571, 4591), 'requests_mock.mock', 'requests_mock.mock', ([], {}), '()\n', (4589, 4591), False, 'import requests_mock\n'), ((4773, 4851), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""'}), "(host='http://oereblex.example.com', language='de', canton='BL')\n", (4787, 4851), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((5421, 5441), 'requests_mock.mock', 'requests_mock.mock', ([], {}), '()\n', (5439, 5441), False, 'import requests_mock\n'), ((5623, 5735), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""', 'related_decree_as_main': '(True)'}), "(host='http://oereblex.example.com', language='de', canton=\n    'BL', related_decree_as_main=True)\n", (5637, 5735), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((6329, 6349), 'requests_mock.mock', 'requests_mock.mock', ([], {}), '()\n', (6347, 6349), False, 'import requests_mock\n'), ((6537, 6639), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""', 'pass_version': '(True)'}), "(host='http://oereblex.example.com', language='de', canton=\n    'BL', pass_version=True)\n", (6551, 6639), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((6800, 6820), 'requests_mock.mock', 'requests_mock.mock', ([], {}), '()\n', (6818, 6820), False, 'import requests_mock\n'), ((7008, 7127), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""', 'pass_version': '(True)', 'version': '"""1.0.0"""'}), "(host='http://oereblex.example.com', language='de', canton=\n    'BL', pass_version=True, version='1.0.0')\n", (7022, 7127), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((7289, 7309), 'requests_mock.mock', 'requests_mock.mock', ([], {}), '()\n', (7307, 7309), False, 'import requests_mock\n'), ((7501, 7579), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {'host': '"""http://oereblex.example.com"""', 'language': '"""de"""', 'canton': '"""BL"""'}), "(host='http://oereblex.example.com', language='de', canton='BL')\n", (7515, 7579), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((7597, 7612), 'tests.mockrequest.MockParameter', 'MockParameter', ([], {}), '()\n', (7610, 7612), False, 'from tests.mockrequest import MockParameter\n'), ((938, 959), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {}), '(**cfg)\n', (952, 959), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((1000, 1029), 'pytest.raises', 'pytest.raises', (['AssertionError'], {}), '(AssertionError)\n', (1013, 1029), False, 'import pytest\n'), ((1043, 1064), 'pyramid_oereb.contrib.sources.document.OEREBlexSource', 'OEREBlexSource', ([], {}), '(**cfg)\n', (1057, 1064), False, 'from pyramid_oereb.contrib.sources.document import OEREBlexSource\n'), ((1484, 1505), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (1503, 1505), False, 'import datetime\n'), ((3413, 3437), 'pytest.raises', 'pytest.raises', (['TypeError'], {}), '(TypeError)\n', (3426, 3437), False, 'import pytest\n'), ((4872, 4887), 'tests.mockrequest.MockParameter', 'MockParameter', ([], {}), '()\n', (4885, 4887), False, 'from tests.mockrequest import MockParameter\n'), ((5783, 5798), 'tests.mockrequest.MockParameter', 'MockParameter', ([], {}), '()\n', (5796, 5798), False, 'from tests.mockrequest import MockParameter\n'), ((6687, 6702), 'tests.mockrequest.MockParameter', 'MockParameter', ([], {}), '()\n', (6700, 6702), False, 'from tests.mockrequest import MockParameter\n'), ((7175, 7190), 'tests.mockrequest.MockParameter', 'MockParameter', ([], {}), '()\n', (7188, 7190), False, 'from tests.mockrequest import MockParameter\n'), ((8375, 8381), 'geolink_formatter.entity.File', 'File', ([], {}), '()\n', (8379, 8381), False, 'from geolink_formatter.entity import Document, File\n'), ((3346, 3367), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (3365, 3367), False, 'import datetime\n'), ((3264, 3316), 'geolink_formatter.entity.File', 'File', (['"""Reference file"""', '"""/api/attachments/4"""', '"""main"""'], {}), "('Reference file', '/api/attachments/4', 'main')\n", (3268, 3316), False, 'from geolink_formatter.entity import Document, File\n'), ((4062, 4083), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (4081, 4083), False, 'import datetime\n'), ((2054, 2075), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (2073, 2075), False, 'import datetime\n'), ((2399, 2420), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (2418, 2420), False, 'import datetime\n'), ((2659, 2680), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (2678, 2680), False, 'import datetime\n'), ((2874, 2895), 'datetime.date.today', 'datetime.date.today', ([], {}), '()\n', (2893, 2895), False, 'import datetime\n'), ((1984, 2028), 'geolink_formatter.entity.File', 'File', (['"""File 1"""', '"""/api/attachments/1"""', '"""main"""'], {}), "('File 1', '/api/attachments/1', 'main')\n", (1988, 2028), False, 'from geolink_formatter.entity import Document, File\n'), ((2256, 2300), 'geolink_formatter.entity.File', 'File', (['"""File 2"""', '"""/api/attachments/2"""', '"""main"""'], {}), "('File 2', '/api/attachments/2', 'main')\n", (2260, 2300), False, 'from geolink_formatter.entity import Document, File\n'), ((2314, 2364), 'geolink_formatter.entity.File', 'File', (['"""File 3"""', '"""/api/attachments/3"""', '"""additional"""'], {}), "('File 3', '/api/attachments/3', 'additional')\n", (2318, 2364), False, 'from geolink_formatter.entity import Document, File\n'), ((2589, 2633), 'geolink_formatter.entity.File', 'File', (['"""File 1"""', '"""/api/attachments/1"""', '"""main"""'], {}), "('File 1', '/api/attachments/1', 'main')\n", (2593, 2633), False, 'from geolink_formatter.entity import Document, File\n')]