#!/usr/bin/python
# -*- coding: utf-8 -*-

import datetime
from rivista.xmpp.utilities import XmppUtilities
from slixmpp.stanza.iq import Iq
import xml.etree.ElementTree as ET

class XmlAtom:

    def error_message(text):
        """Error message in RFC 4287: The Atom Syndication Format."""
        title = 'Rivista'
        subtitle = 'XMPP Journal Publisher'
        description = ('This is a syndication feed generated with Rivista, an XMPP '
                       'Journal Publisher, which conveys XEP-0060: Publish-'
                       'Subscribe nodes to standard RFC 4287: The Atom Syndication '
                       'Format.')
        language = 'en'
        feed = ET.Element("feed")
        feed.set('xmlns', 'http://www.w3.org/2005/Atom')
        ET.SubElement(feed, 'title', {'type': 'text'}).text = title
        ET.SubElement(feed, 'subtitle', {'type': 'text'}).text = subtitle
        ET.SubElement(feed, 'author', {'name':'Rivista','email':'rivista@schimon.i2p'})
        ET.SubElement(feed, 'generator', {
            'uri': 'https://git.xmpp-it.net/sch/Rivista',
            'version': '0.1'}).text = 'Rivista XJP'
        ET.SubElement(feed, 'updated').text = datetime.datetime.now(datetime.UTC).isoformat()
        entry = ET.SubElement(feed, 'entry')
        ET.SubElement(entry, 'title').text = 'Error'
        ET.SubElement(entry, 'id').text = 'rivista-error'
        ET.SubElement(entry, 'updated').text = datetime.datetime.now(datetime.UTC).isoformat()
        ET.SubElement(entry, 'published').text = datetime.datetime.now(datetime.UTC).isoformat()
        # ET.SubElement(entry, 'summary', {'type': summary_type_text}).text = summary_text
        ET.SubElement(entry, 'content', {'type': 'text'}).text = text
        return ET.tostring(feed, encoding='unicode')

    def extract_atom(iq: Iq):
        """Extract data from an Atom Syndication Format (RFC 4287) of a Publish-Subscribe (XEP-0060) node item."""
        jid = iq['from'].bare
        node = iq['pubsub']['items']['node']
        atom = {}
        atom['title'] = jid
        atom['subtitle'] = node
        atom['language'] = iq['pubsub']['items']['lang']
        atom['items'] = []
        items = iq['pubsub']['items']
        for item in list(items)[::-1]:
            atom_item = {}
            item_payload = item['payload']
            namespace = '{http://www.w3.org/2005/Atom}'
            title = item_payload.find(namespace + 'title')
            links = item_payload.find(namespace + 'link')
            if (not isinstance(title, ET.Element) and
                not isinstance(links, ET.Element)): continue
            title_text = 'No title' if title == None else title.text
            atom_item['title'] = title_text
            if isinstance(links, ET.Element):
                atom_item['links'] = []
                for link in item_payload.findall(namespace + 'link'):
                    link_href = link.attrib['href'] if 'href' in link.attrib else ''
                    link_type = link.attrib['type'] if 'type' in link.attrib else ''
                    link_rel = link.attrib['rel'] if 'rel' in link.attrib else ''
                    atom_item['links'].append({'href': link_href,
                                               'rel': link_rel,
                                               'type': link_type})
            contents = item_payload.find(namespace + 'content')
            atom_item['contents'] = []
            if isinstance(contents, ET.Element):
                for content in item_payload.findall(namespace + 'content'):
                    if not content.text: continue
                    content_text = content.text
                    content_type = content.attrib['type'] if 'type' in content.attrib else 'html'
                    content_type_text = 'html' if 'html' in content_type else 'text'
                    atom_item['contents'].append({'text' : content_text,
                                                  'type' : content_type_text})
            else:
                summary = item_payload.find(namespace + 'summary')
                summary_text = summary.text if summary else None
                if summary_text:
                    summary_type = summary.attrib['type'] if 'type' in summary.attrib else 'html'
                    summary_type_text = 'html' if 'html' in summary_type else 'text'
                    atom_item['contents'].append(summary_text)
               # else:
               #     atom_item['contents'].append('No content.')
            published = item_payload.find(namespace + 'published')
            published_text = '' if published == None else published.text
            atom_item['published'] = published_text
            updated = item_payload.find(namespace + 'updated')
            updated_text = '' if updated == None else updated.text
            atom_item['updated'] = updated_text
            atom_item['authors'] = []
            authors = item_payload.find(namespace + 'author')
            if isinstance(authors, ET.Element):
                for author in item_payload.findall(namespace + 'author'):
                    atom_item_author = {}
                    author_email = author.find(namespace + 'email')
                    if author_email is not None:
                        author_email_text = author_email.text
                        if author_email_text:
                            atom_item_author['email'] = author_email_text
                    else:
                        author_email_text = None
                    author_uri = author.find(namespace + 'uri')
                    if author_uri is not None:
                        author_uri_text = author_uri.text
                        if author_uri_text:
                            atom_item_author['uri'] = author_uri_text
                    else:
                        author_uri_text = None
                    author_name = author.find(namespace + 'name')
                    if author_name is not None and author_name.text:
                        author_name_text = author_name.text
                    else:
                        author_name_text = author_uri_text or author_email_text
                    atom_item_author['name'] = author_name_text
                    atom_item['authors'].append(atom_item_author)
            categories = item_payload.find(namespace + 'category')
            atom_item['categories'] = []
            if isinstance(categories, ET.Element):
                for category in item_payload.findall(namespace + 'category'):
                    if 'term' in category.attrib and category.attrib['term']:
                        category_term = category.attrib['term']
                        atom_item['categories'].append(category_term)
            identifier = item_payload.find(namespace + 'id')
            if identifier is not None and identifier.attrib: print(identifier.attrib)
            identifier_text = item['id'] if identifier == None else identifier.text
            atom_item['id'] = identifier_text
            #atom_item['id'] = item['id']
            atom['items'].append(atom_item)
        return atom

    # generate_rfc_4287
    def generate_atom_post(atom: dict, pubsub: str, node: str, link: str):
        """Generate an Atom Syndication Format (RFC 4287) from a Publish-Subscribe (XEP-0060) node items."""
        # link = XmppUtilities.form_a_node_link(pubsub, node)
        # subtitle = 'XMPP PubSub Syndication Feed'
        description = ('This is a syndication feed generated with Rivista, an XMPP '
                       'Journal Publisher, which conveys XEP-0060: Publish-'
                       'Subscribe nodes to standard RFC 4287: The Atom Syndication '
                       'Format.')
        e_feed = ET.Element("feed")
        e_feed.set('xmlns', 'http://www.w3.org/2005/Atom')
        ET.SubElement(e_feed, 'title', {'type': 'text'}).text = atom['title']
        ET.SubElement(e_feed, 'subtitle', {'type': 'text'}).text = atom['subtitle']
        ET.SubElement(e_feed, 'link', {'rel': 'self', 'href': link})
        ET.SubElement(e_feed, 'generator', {
            'uri': 'https://git.xmpp-it.net/sch/Rivista',
            'version': '0.1'}).text = 'Rivista XJP'
        ET.SubElement(e_feed, 'updated').text = datetime.datetime.now(datetime.UTC).isoformat()
        for item in atom['items']:
            e_entry = ET.SubElement(e_feed, 'entry')
            ET.SubElement(e_entry, 'title').text = item['title']
            links = item['links'] if 'links' in item else None
            if links:
                for link in links:
                    ET.SubElement(e_entry, 'link', {'href': link['href'],
                                                    'rel': link['rel'],
                                                    'type': link['type']})
            else:
                # NOTE What does this instruction line do?
                ET.SubElement(e_entry, 'content', {'href': ''})
            link_xmpp = XmppUtilities.form_an_item_link(pubsub, node, item['id'])
            ET.SubElement(e_entry, 'link', {'href': link_xmpp,
                                            'rel': 'alternate',
                                            'type': 'x-scheme-handler/xmpp'})
            contents = item['contents'] if 'contents' in item else None
            if contents:
                for content in contents:
                    ET.SubElement(e_entry, 'content', {'type': content['type']}).text = content['text']
            else:
                ET.SubElement(e_entry, 'content').text = 'No content.'
            ET.SubElement(e_entry, 'published').text = item['published']
            ET.SubElement(e_entry, 'updated').text = item['updated']
            authors = item['authors'] if 'authors' in item else None
            if authors:
                for author in authors:
                    e_author = ET.SubElement(e_entry, 'author')
                    if 'email' in author and author['email']:
                        ET.SubElement(e_author, 'email').text = author['email']
                    if 'uri' in author and author['uri']:
                        ET.SubElement(e_entry, 'uri').text = author['uri']
                        ET.SubElement(e_author, 'uri').text = author['uri']
                    ET.SubElement(e_author, 'name').text = author['name'] or author['uri'] or author['email']
            categories = item['categories']
            if categories:
                for category in categories:
                    ET.SubElement(e_entry, 'category', {'term': category})

            ET.SubElement(e_entry, 'id').text = item['id']
        return ET.tostring(e_feed, encoding='unicode')

    # generate_rfc_4287
    def generate_atom_comment(atom: dict, pubsub: str, node: str, link: str):
        """Generate an Atom Syndication Format (RFC 4287) from a Publish-Subscribe (XEP-0060) node items."""
        # link = XmppUtilities.form_a_node_link(pubsub, node)
        # subtitle = 'XMPP PubSub Syndication Feed'
        description = ('This is a syndication feed generated with Rivista, an XMPP '
                       'Journal Publisher, which conveys XEP-0060: Publish-'
                       'Subscribe nodes to standard RFC 4287: The Atom Syndication '
                       'Format.')
        e_feed = ET.Element("feed")
        e_feed.set('xmlns', 'http://www.w3.org/2005/Atom')
        ET.SubElement(e_feed, 'title', {'type': 'text'}).text = atom['title']
        ET.SubElement(e_feed, 'subtitle', {'type': 'text'}).text = atom['subtitle']
        ET.SubElement(e_feed, 'link', {'rel': 'self', 'href': link})
        ET.SubElement(e_feed, 'generator', {
            'uri': 'https://git.xmpp-it.net/sch/Rivista',
            'version': '0.1'}).text = 'Rivista XJP'
        ET.SubElement(e_feed, 'updated').text = datetime.datetime.now(datetime.UTC).isoformat()
        for item in atom['items']:
            e_entry = ET.SubElement(e_feed, 'entry')
            ET.SubElement(e_entry, 'title').text = item['authors'][0]['name']
            links = item['links'] if 'links' in item else None
            if links:
                for link in links:
                    ET.SubElement(e_entry, 'link', {'href': link['href'],
                                                    'rel': link['rel'],
                                                    'type': link['type']})
            else:
                # NOTE What does this instruction line do?
                ET.SubElement(e_entry, 'content', {'href': ''})
            link_xmpp = XmppUtilities.form_an_item_link(pubsub, node, item['id'])
            ET.SubElement(e_entry, 'link', {'href': link_xmpp,
                                            'rel': 'alternate',
                                            'type': 'x-scheme-handler/xmpp'})
            contents = item['contents'] if 'contents' in item else None
            if contents:
                for content in contents:
                    ET.SubElement(e_entry, 'content', {'type': content['type']}).text = content['text']
            else:
                ET.SubElement(e_entry, 'content').text = 'No content.'
            ET.SubElement(e_entry, 'published').text = item['published']
            ET.SubElement(e_entry, 'updated').text = item['updated']
            authors = item['authors'] if 'authors' in item else None
            if authors:
                for author in authors:
                    e_author = ET.SubElement(e_entry, 'author')
                    if 'email' in author and author['email']:
                        ET.SubElement(e_author, 'email').text = author['email']
                    if 'uri' in author and author['uri']:
                        ET.SubElement(e_entry, 'uri').text = author['uri']
                        ET.SubElement(e_author, 'uri').text = author['uri']
                    ET.SubElement(e_author, 'name').text = author['name'] or author['uri'] or author['email']
            categories = item['categories']
            if categories:
                for category in categories:
                    ET.SubElement(e_entry, 'category', {'term': category})

            ET.SubElement(e_entry, 'id').text = item['id']
        return ET.tostring(e_feed, encoding='unicode')
