# -*- coding: utf-8; -*-
#
# This file is part of Superdesk.
#
# Copyright 2013, 2014 Sourcefabric z.u. and contributors.
#
# For the full copyright and license information, please see the
# AUTHORS and LICENSE files distributed with this source code, or
# at https://www.sourcefabric.org/superdesk/license


import os
from superdesk import config
from superdesk.tests import TestCase

from superdesk.etree import etree
from superdesk.io.feed_parsers.nitf import NITFFeedParser


class NITFTestCase(TestCase):
    vocab = [{"_id": "genre", "items": [{"name": "Current"}]}]

    def setUp(self):
        with self.app.app_context():
            self.app.data.insert("vocabularies", self.vocab)
        dirname = os.path.dirname(os.path.realpath(__file__))
        fixture = os.path.normpath(os.path.join(dirname, "../fixtures", self.filename))
        provider = {"name": "Test"}
        with open(fixture, "rb") as f:
            self.nitf = f.read()
            self.item = NITFFeedParser().parse(etree.fromstring(self.nitf), provider)


class AAPTestCase(NITFTestCase):
    filename = "aap.xml"

    def test_headline(self):
        self.assertEqual(self.item.get("headline"), "The main stories on today's 1900 ABC TV news")

    def test_slugline(self):
        self.assertEqual(self.item.get("slugline"), "Monitor 1900 ABC News")

    def test_subjects(self):
        self.assertEqual(len(self.item.get("subject")), 4)
        self.assertIn({"qcode": "02000000", "name": "Justice"}, self.item.get("subject"))
        self.assertIn({"qcode": "02003000", "name": "Police"}, self.item.get("subject"))
        self.assertIn({"qcode": "02003001", "name": "law enforcement"}, self.item.get("subject"))
        self.assertIn({"qcode": "02003002", "name": "investigation"}, self.item.get("subject"))

    def test_guid(self):
        self.assertEqual(self.item.get("guid"), "AAP.115314987.5417374")
        self.assertEqual(self.item.get("guid"), self.item.get("uri"))

    def test_type(self):
        self.assertEqual(self.item.get("type"), "text")

    def test_urgency(self):
        self.assertEqual(self.item.get("urgency"), 5)

    def test_dateline(self):
        self.assertEqual(self.item.get("dateline", {}).get("located", {}).get("city"), "Sydney")

    def test_byline(self):
        self.assertEqual(self.item.get("byline"), "By John Doe")

    def test_abstract(self):
        self.assertEqual(self.item.get("abstract"), "The main stories on today's 1900 ABC TV news")

    def test_dates(self):
        self.assertEqual(self.item.get("firstcreated").isoformat(), "2013-10-20T08:27:51+00:00")
        self.assertEqual(self.item.get("versioncreated").isoformat(), "2013-10-20T08:27:51+00:00")

    def test_content(self):
        text = "<p>   1A) More extreme weather forecast over the next few days the <br/>fire situation is likely"
        self.assertIn(text, self.item.get("body_html"))
        self.assertIsInstance(self.item.get("body_html"), type(""))
        self.assertNotIn("<body.content>", self.item.get("body_html"))

    def test_pubstatus(self):
        self.assertEqual("usable", self.item.get("pubstatus"))

    def test_ingest_provider_sequence(self):
        self.assertEqual(self.item.get("ingest_provider_sequence"), "1747")

    def test_anpa_category(self):
        self.assertEqual(self.item.get("anpa_category")[0]["qcode"], "a")

    def test_word_count(self):
        self.assertIsInstance(self.item.get("word_count"), int)


class APExampleTestCase(NITFTestCase):
    filename = "ap-nitf.xml"

    def test_headline(self):
        self.assertEqual(self.item.get("headline"), "Can trading pollution like stocks help fight climate change?")

    def test_byline(self):
        self.assertEqual(self.item.get("byline"), "By BERNARD CONDON")

    def test_ednote(self):
        self.assertEqual(self.item.get("ednote"), "For global distribution")

    def test_word_count(self):
        self.assertIsInstance(self.item.get("word_count"), int)


class IPTCExampleTestCase(NITFTestCase):
    filename = "nitf-fishing.xml"

    def test_headline(self):
        self.assertEqual(self.item.get("headline"), "Weather and Tide Updates for Norfolk")

    def test_pubstatus(self):
        self.assertEqual("canceled", self.item.get("pubstatus"))

    def test_guid(self):
        self.assertEqual("iptc.321656141.b", self.item.get("guid"))

    def test_subjects(self):
        self.assertEqual(3, len(self.item.get("subject")))

    def test_place(self):
        places = self.item.get("place", [])
        self.assertEqual(1, len(places))
        self.assertEqual("Norfolk", places[0]["name"])
        self.assertEqual("US", places[0]["code"])
        self.assertEqual("Norfolk", places[0]["qcode"])

    def test_expiry(self):
        self.assertEqual("2012-02-26T14:30:00+00:00", self.item.get("expiry").isoformat())

    def test_keywords(self):
        self.assertIn("fishing", self.item.get("keywords"))

    def test_ednote(self):
        self.assertEqual("Today begins an expanded format of this popular column.", self.item.get("ednote"))

    def test_byline(self):
        self.assertEqual("By Alan Karben", self.item.get("byline"))

    def test_word_count(self):
        self.assertIsInstance(self.item.get("word_count"), int)


class PATestCase(NITFTestCase):
    filename = "pa1.xml"

    def test_headline(self):
        self.assertEqual(self.item.get("headline"), "PA SPORT TRIVIA (OCTOBER 14)")

    def test_pubstatus(self):
        self.assertEqual("usable", self.item.get("pubstatus"))

    def test_guid(self):
        self.assertEqual("af1f7ad5-5619-49de-84cc-2e608538c77fSSS-3-1", self.item.get("guid"))
        self.assertEqual(self.item.get("format"), "HTML")

    def test_subjects(self):
        self.assertEqual(4, len(self.item.get("subject")))

    def test_keywords(self):
        self.assertIn("Trivia (Oct 14)", self.item.get("keywords"))

    def test_word_count(self):
        self.assertIsInstance(self.item.get("word_count"), int)


class PATestCase2(NITFTestCase):
    filename = "pa2.xml"

    def test_headline(self):
        self.assertEqual(self.item.get("headline"), "1 SOCCER INT-Teams")

    def test_pubstatus(self):
        self.assertEqual("usable", self.item.get("pubstatus"))

    def test_guid(self):
        self.assertEqual("T201510140143580001T", self.item.get("guid"))
        self.assertEqual(self.item.get("format"), "preserved")

    def test_guid_2(self):
        self.assertEqual(self.item.get("type"), "text")

    def test_subjects(self):
        self.assertEqual(0, len(self.item.get("subject")))

    def test_keywords(self):
        self.assertIn("INT-Teams", self.item.get("keywords"))

    def test_word_count(self):
        self.assertEqual(58, self.item.get("word_count"))


class ParseSubjects(TestCase):
    def test_get_subjects(self):
        xml = (
            b'<?xml version="1.0" encoding="UTF-8"?>'
            b"<nitf><head>"
            b'<tobject tobject.type="News">'
            b'<tobject.property tobject.property.type="Current" />'
            b'<tobject.subject tobject.subject.refnum="02003000" '
            b'tobject.subject.type="Justice" tobject.subject.matter="Police" />'
            b"</tobject></head></nitf>"
        )
        subjects = NITFFeedParser().get_subjects(etree.fromstring(xml))
        self.assertEqual(len(subjects), 2)
        self.assertIn({"qcode": "02000000", "name": "Justice"}, subjects)
        self.assertIn({"qcode": "02003000", "name": "Police"}, subjects)

    def test_get_subjects_with_invalid_qcode(self):
        xml = (
            b'<?xml version="1.0" encoding="UTF-8"?>'
            b"<nitf><head>"
            b'<tobject tobject.type="News">'
            b'<tobject.property tobject.property.type="Current" />'
            b'<tobject.subject tobject.subject.refnum="00000000" '
            b'tobject.subject.type="Justice" tobject.subject.matter="Police" />'
            b"</tobject></head></nitf>"
        )
        subjects = NITFFeedParser().get_subjects(etree.fromstring(xml))
        self.assertEqual(len(subjects), 0)


class MappingTestCase(TestCase):
    filename = "mapping_test.xml"
    mapping = {
        "subject": {"update": True, "key_hook": lambda item, value: item.setdefault("subject", []).extend(value)},
        "subject_test": {
            "callback": lambda _: ["TEST OK"],
            "key_hook": lambda item, value: item.setdefault("subject", []).extend(value),
        },
    }

    def setUp(self):
        config.NITF_MAPPING = self.mapping
        dirname = os.path.dirname(os.path.realpath(__file__))
        fixture = os.path.normpath(os.path.join(dirname, "../fixtures", self.filename))
        provider = {"name": "Test"}
        with open(fixture, "rb") as f:
            self.nitf = f.read()
            self.item = NITFFeedParser().parse(etree.fromstring(self.nitf), provider)

    def test_update_and_hook(self):
        subjects = self.item.get("subject")
        # have we got both items ?
        self.assertEqual(len(subjects), 2)
        # the initial updated subject need to be here
        self.assertIn({"qcode": "02000000", "name": "Kriminalitet og rettsvesen"}, subjects)
        # and our key from subject_test need to be here too
        self.assertIn("TEST OK", subjects)

    def tearDown(self):
        del config.NITF_MAPPING


class HandleInvalidFieldsTestCase(NITFTestCase):
    filename = "handle_invalid_fields.xml"

    def test_dates(self):
        self.assertEqual(self.item.get("firstcreated").isoformat(), "2020-07-03T20:51:36+00:00")
        self.assertEqual(self.item.get("versioncreated").isoformat(), "2020-07-03T20:51:36+00:00")

    def test_expiry(self):
        self.assertEqual(self.item.get("expiry"), None)

    def test_keywords(self):
        self.assertEqual(len(self.item.get("keywords")), 0)


class NTBTestCase(NITFTestCase):
    filename = "nitf-ntb.xml"

    def test_place(self):
        self.assertEqual([], self.item.get("place"))
