import time
from xml.dom import minidom
from xml.etree import ElementTree
from xml.etree.ElementTree import Element, SubElement
from elifearticle import parse as articleparse
from elifearticle.article import ArticleDate
from elifecleaner import parse
from elifecleaner.utils import pad_msid

JOURNAL_ID_TYPES = ["nlm-ta", "publisher-id"]

NAMESPACE_MAP = {
    "xmlns:mml": "http://www.w3.org/1998/Math/MathML",
    "xmlns:xlink": "http://www.w3.org/1999/xlink",
}

MEDIA_CONTENT_TYPE = "glencoe play-in-place height-250 width-310"

DTD_VERSION = "1.1d1"


def article_from_xml(xml_file_path):
    return articleparse.build_article_from_xml(xml_file_path)


def set_pub_date(parent, article, pub_type):
    "set XML pub-date tag to values from an article date"
    pub_date = article.get_date(pub_type)
    if pub_date:
        date_tag = SubElement(parent, "pub-date")
        date_tag.set("date-type", pub_type)
        if pub_date.publication_format:
            date_tag.set("publication-format", pub_date.publication_format)
        day = SubElement(date_tag, "day")
        day.text = str(pub_date.date.tm_mday).zfill(2)
        month = SubElement(date_tag, "month")
        month.text = str(pub_date.date.tm_mon).zfill(2)
        year = SubElement(date_tag, "year")
        year.text = str(pub_date.date.tm_year)


def set_article_meta(parent, article):
    "set XML article-meta tag and tags found inside it"
    article_meta = SubElement(parent, "article-meta")

    # article-id pub-id-type="publisher-id"
    if article.manuscript:
        pub_id_type = "publisher-id"
        article_id = SubElement(article_meta, "article-id")
        article_id.text = pad_msid(article.manuscript)
        article_id.set("pub-id-type", pub_id_type)

    # article-id pub-id-type="doi"
    if article.doi:
        pub_id_type = "doi"
        article_id = SubElement(article_meta, "article-id")
        article_id.text = article.doi
        article_id.set("pub-id-type", pub_id_type)

    set_pub_date(article_meta, article, "publication")


def set_front(parent, journal_data, article):
    "set XML front tag and the tags found inside it"
    front_tag = SubElement(parent, "front")
    journal_meta = SubElement(front_tag, "journal-meta")

    # journal-id
    if journal_data.get("journal_ids"):
        for journal_id_type, value in journal_data.get("journal_ids").items():
            # concatenate the config name to look for the value
            if journal_id_type:
                journal_id = SubElement(journal_meta, "journal-id")
                journal_id.set("journal-id-type", journal_id_type)
                journal_id.text = value
    # journal-title-group
    journal_title_group = SubElement(journal_meta, "journal-title-group")

    # journal-title
    if journal_data.get("journal_title"):
        journal_title_tag = SubElement(journal_title_group, "journal-title")
        journal_title_tag.text = journal_data.get("journal_title")

    # publisher
    if journal_data.get("publisher_name"):
        publisher = SubElement(journal_meta, "publisher")
        publisher_name_tag = SubElement(publisher, "publisher-name")
        publisher_name_tag.text = journal_data.get("publisher_name")

    set_article_meta(front_tag, article)


def set_body(parent, video_data):
    "set XML body tag contents"
    body_tag = SubElement(parent, "body")
    # video media tags
    for video in video_data:
        media_tag = SubElement(body_tag, "media")
        media_tag.set("xlink:href", video.get("video_filename"))
        media_tag.set("id", video.get("video_id"))
        media_tag.set("content-type", MEDIA_CONTENT_TYPE)
        media_tag.set("mimetype", "video")


def output_xml(root, pretty=False, indent=""):
    "output root XML Element to a string"
    encoding = "utf-8"
    rough_string = ElementTree.tostring(root, encoding)
    reparsed = minidom.parseString(rough_string)

    if pretty is True:
        return reparsed.toprettyxml(indent, encoding=encoding)
    return reparsed.toxml(encoding=encoding)


def generate_xml(article, journal_data, video_data, pretty=True, indent=""):
    "from jats_content generate final JATS output"

    # set the date to today
    article_date = ArticleDate("publication", time.gmtime())
    article_date.publication_format = "electronic"
    article.add_date(article_date)

    # Create the root XML node
    root = Element("article")
    # set attributes
    root.set("dtd-version", DTD_VERSION)
    root.set("article-type", article.article_type)
    # set namespaces
    for prefix, url in NAMESPACE_MAP.items():
        root.set(prefix, url)

    set_front(root, journal_data, article)
    set_body(root, video_data)

    return output_xml(root, pretty, indent)


def glencoe_xml(xml_file_path, video_data, pretty=True, indent=""):
    "generate XML to be submitted to Glencoe"
    # build an Article object from the XML
    article, error_count = article_from_xml(xml_file_path)
    # collect journal data from the XML elementtree
    root = parse.parse_article_xml(xml_file_path)
    journal_ids = parse.xml_journal_id_values(root)
    filtered_journal_ids = {
        key: value for key, value in journal_ids.items() if key in JOURNAL_ID_TYPES
    }
    journal_title = parse.xml_journal_title(root)
    publisher_name = parse.xml_publisher_name(root)
    journal_data = {
        "journal_ids": filtered_journal_ids,
        "journal_title": journal_title,
        "publisher_name": publisher_name,
    }
    return generate_xml(article, journal_data, video_data, pretty, indent)
