from xml.etree import ElementTree as ET
from xml.dom import minidom
import datetime


class XMLBuilder:
    def __init__(self, cp_id, media=None, **kwargs):
        self.providerID = cp_id
        self.assetID = kwargs["asset_id"]
        self.serialNo = kwargs["serial_no"]
        self.media = media
        self.kwargs = kwargs
        self.root = None
        self.default_ns = "http://www.cablelabs.com/VODSchema/default"
        self.adi_ns = "http://www.cablelabs.com/VODSchema/adi"
        self.vod_ns = "http://www.cablelabs.com/VODSchema/vod"
        self.group_tags = {"register": "OpenGroupAsset", "update": "ReplaceGroupAsset", "delete": "DropGroupAsset"}
        self.metadata_tags = {"register": "AddMetadataAsset", "update": "ReplaceMetadataAsset",
                              "delete": "RemoveMetadataAsset"}
        self.content_tags = {"register": "AcceptContentAsset", "update": "ReplaceContentAsset",
                             "delete": "DestroyContentAsset"}

    def create_root(self):
        ET.register_namespace('', self.default_ns)
        ET.register_namespace('adi', self.adi_ns)
        ET.register_namespace('vod', self.vod_ns)
        self.root = ET.Element("{%s}ADI2" % self.adi_ns)

    def create_open_group_asset(self, action):
        open_group_asset = ET.SubElement(self.root, "{%s}%s" % (self.adi_ns, self.group_tags[action]))
        ET.SubElement(open_group_asset, "{%s}VODRelease" % self.vod_ns,
                      attrib={"providerID": self.providerID, "assetID": self.assetID, "serialNo": self.serialNo})

    def create_content_asset(self, _type, action):
        content_asset = ET.SubElement(self.root, "{%s}%s" % (self.adi_ns, self.content_tags[action]),
                                      attrib={"type": _type})
        return content_asset

    def create_metadata_asset(self, _type, action):
        metadata_asset = ET.SubElement(self.root, "{%s}%s" % (self.adi_ns, self.metadata_tags[action]),
                                       attrib={"groupProviderID": self.providerID,
                                               "groupAssetID": self.assetID, "type": _type})
        return metadata_asset

    def create_ser_metadata_asset_title(self, action):
        metadata_asset_title = self.create_metadata_asset("Title", action)
        metadata_title = self.create_vod_element(metadata_asset_title, "Title")
        self.create_vod_element(metadata_title, "TitleFull", self.media.name)
        self.create_vod_element(metadata_title, "ShowType", self.kwargs["show_type"])
        self.create_vod_element(metadata_title, "SummaryMedium", self.media.storyline)
        self.create_vod_element(metadata_title, "SummaryShort", self.kwargs["focus"])
        self.create_vod_element(metadata_title, "RunTime", str(int(self.media.total_seconds)))
        self.create_vod_element(metadata_title, "CountryOfOrigin", self.kwargs["country_origin"])
        self.create_vod_element(self.create_vod_element_attr(metadata_title, "Actor", {"type": "Actor"}),
                                "LastNameFirst",
                                self.kwargs["actors"])
        self.create_vod_element(self.create_vod_element(metadata_title, "Director"), "LastNameFirst",
                                self.kwargs["directors"])
        self.create_vod_element(metadata_title, "Items", str(self.media.episodes))
        self.create_vod_element(metadata_title, "Language", self.media.languages)
        self.create_vod_element(metadata_title, "Keyword", "")
        self.create_vod_element(metadata_title, "Tag", "")
        self.create_vod_element(metadata_title, "Year", str(self.media.year))
        self.create_vod_element(metadata_title, "releaseTime", self.media.date_published)
        self.create_vod_element(metadata_title, "IMDbGrade", self.media.douban_score)

    def create_sub_metadata_asset_title(self, action):
        metadata_asset_title = self.create_metadata_asset("Title", action)
        metadata_title = self.create_vod_element(metadata_asset_title, "Title")
        self.create_vod_element(metadata_title, "TitleFull", self.kwargs["episode"]["title"])
        self.create_vod_element(metadata_title, "ShowType", self.kwargs["show_type"])
        self.create_vod_element(metadata_title, "SummaryMedium", self.media.storyline)
        self.create_vod_element(metadata_title, "SummaryShort", self.kwargs["focus"])
        self.create_vod_element(metadata_title, "RunTime", str(int(self.media.total_seconds)))
        self.create_vod_element(metadata_title, "CountryOfOrigin", self.kwargs["country_origin"])
        self.create_vod_element(self.create_vod_element_attr(metadata_title, "Actor", {"type": "Actor"}),
                                "LastNameFirst",
                                self.kwargs["actors"])
        self.create_vod_element(self.create_vod_element_attr(metadata_title, "Actor", {"type": "Actress"}),
                                "LastNameFirst", self.kwargs.get("actresses"))
        self.create_vod_element(self.create_vod_element(metadata_title, "Director"), "LastNameFirst",
                                self.kwargs["directors"])
        self.create_vod_element(metadata_title, "Language", self.media.languages)
        self.create_vod_element(metadata_title, "Keyword", "")
        self.create_vod_element(metadata_title, "Tag", "")
        self.create_vod_element(metadata_title, "Year", str(self.media.year))
        self.create_vod_element(metadata_title, "releaseTime", self.media.date_published)
        self.create_vod_element(metadata_title, "EpisodeID", self.kwargs["episode"]["serial_num"])
        self.create_vod_element(metadata_title, "IssueNumber")
        self.create_vod_element(metadata_title, "SkipStartTime")
        self.create_vod_element(metadata_title, "SkipEndTime")

    def create_ser_metadata_asset_category(self, action):
        metadata_asset_category = self.create_metadata_asset("CategoryPath", action)
        category_path = self.create_vod_element(metadata_asset_category, "CategoryPath")
        self.create_vod_element(category_path, "Classification", self.kwargs["type"])
        self.create_vod_element(category_path, "Category", self.kwargs["type2"])

    def create_ser_metadata_asset_copyright(self, action):
        metadata_asset_copyright = self.create_metadata_asset("Copyright", action)
        copyright = self.create_vod_element(metadata_asset_copyright, "Copyright")
        self.create_adi_element(copyright, "AssetLifetime",
                                {"startDateTime": self.kwargs["vst"],
                                 "endDateTime": self.kwargs["vet"]})
        self.create_vod_element(copyright, "Terminal", "1")
        self.create_vod_element(copyright, "VideoLicense", "")
        self.create_vod_element(copyright, "PublishNo", self.kwargs["publish_no"])
        self.create_vod_element(copyright, "AuthorserilNo", "")
        self.create_vod_element(copyright, "CopyArea", "")
        self.create_vod_element(copyright, "Copyright", "SY")

    def create_content_video(self, action):
        data = self.kwargs["video"]
        content_video = self.create_content_asset("Video", action)
        video = ET.SubElement(content_video, "{%s}Video" % self.vod_ns,
                              attrib={"providerID": self.providerID,
                                      "assetID": data["assetID"],
                                      "fileName": data["fileName"],
                                      "fileSize": data["fileSize"],
                                      "transferContentURL": data["url"]})

        self.create_vod_element(video, "Duration", data["duration"])
        self.create_vod_element(video, "Bitrate", data["bit_rate"])
        self.create_vod_element(video, "GraphicsMode", "0")
        self.create_vod_element(video, "Usage", data["usage"])
        self.create_vod_element(video, "IsDRM", "1")
        self.create_vod_element(video, "IsChange", data["is_change"])

    def create_content_image(self, data, action):
        content_image = self.create_content_asset("Image", action)
        image = ET.SubElement(content_image, "{%s}Image" % self.vod_ns,
                              attrib={"providerID": self.providerID,
                                      "assetID": data["assetID"],
                                      "fileName": data["filename"],
                                      "fileSize": data["len_size"],
                                      "transferContentURL": data["url"],
                                      "imageEncodingProfile": data["profile"]})
        ET.SubElement(image, "{%s}ImagePixels" % self.vod_ns,
                      {"horizontalPixels": data["h_pixs"],
                       "verticalPixels": data["v_pixs"]})
        self.create_vod_element(image, "IsChange", data["is_change"])
        self.create_vod_element(image, "MimeType", data["_type"])

    def create_content_images(self, action):
        img_list = self.kwargs["img_list"]
        for i in range(len(img_list)):
            self.create_content_image(img_list[i], action)

    def create_associate_content(self, data, _type):

        self.create_adi_element(self.root, "AssociateContent", {"type": _type,
                                                                "groupProviderID": self.providerID,
                                                                "groupAssetID": self.assetID,
                                                                "providerID": self.providerID,
                                                                "assetID": data["assetID"]})

    def create_associate_contents(self):
        video = self.kwargs.get("video")
        if video:
            self.create_associate_content(video, "Video")
        img_list = self.kwargs["img_list"]
        for i in range(len(img_list)):
            self.create_associate_content(img_list[i], "Image")

    def create_associate_group(self):
        self.create_adi_element(self.root, "AssociateGroup", {
            "groupProviderID": self.providerID,
            "providerID": self.providerID,
            "assetID": self.assetID,
            "targetGroupAssetID": self.kwargs["parent_id"]
        })

    def create_vod_element_attr(self, parent_node, tag_name, attr):
        element = ET.SubElement(parent_node, "{%s}%s" % (self.vod_ns, tag_name), attr)
        return element

    def create_vod_element(self, parent_node, tag_name, text=None):
        element = ET.SubElement(parent_node, "{%s}%s" % (self.vod_ns, tag_name))
        if text:
            element.text = text
        return element

    def create_adi_element(self, parent_node, tag_name, attr):
        element = ET.SubElement(parent_node, "{%s}%s" % (self.adi_ns, tag_name), attrib=attr)
        return element

    def create_series(self, action):
        self.create_root()
        self.create_open_group_asset(action)
        self.create_ser_metadata_asset_title(action)
        self.create_ser_metadata_asset_category(action)
        self.create_ser_metadata_asset_copyright(action)
        self.create_content_images(action)
        self.create_associate_contents()

    def create_sub_series(self, action):
        self.create_root()
        self.create_open_group_asset(action)
        self.create_sub_metadata_asset_title(action)
        self.create_ser_metadata_asset_category(action)
        self.create_ser_metadata_asset_copyright(action)
        self.create_content_video(action)
        self.create_content_images(action)
        self.create_associate_contents()
        self.create_associate_group()

    def create_movie(self, action):
        self.create_root()
        self.create_open_group_asset(action)
        self.create_ser_metadata_asset_title(action)
        self.create_ser_metadata_asset_category(action)
        self.create_ser_metadata_asset_copyright(action)
        self.create_content_video(action)
        self.create_content_images(action)
        self.create_associate_contents()

    @staticmethod
    def build_movie(cp_id, media, action, **kwargs):
        builder = XMLBuilder(cp_id, media, **kwargs)
        builder.create_movie(action)
        rough_string = ET.tostring(builder.root, encoding='UTF-8')
        new_string = minidom.parseString(rough_string).toprettyxml(encoding="UTF-8")
        return new_string

    @staticmethod
    def build_sub_series(cp_id, media, action, **kwargs):
        builder = XMLBuilder(cp_id, media, **kwargs)
        builder.create_sub_series(action)
        rough_string = ET.tostring(builder.root, encoding='UTF-8')
        new_string = minidom.parseString(rough_string).toprettyxml(encoding="UTF-8")
        return new_string

    @staticmethod
    def build_series(cp_id, media, action, **kwargs):
        builder = XMLBuilder(cp_id, media, **kwargs)
        builder.create_series(action)
        rough_string = ET.tostring(builder.root, encoding='UTF-8')
        new_string = minidom.parseString(rough_string).toprettyxml(encoding="UTF-8")
        return new_string

    @classmethod
    def gen_utf_time(cls):
        today = datetime.datetime.today()
        main_time = today.strftime("%Y-%m-%dT%H:%M:%S.{}Z")
        microseconds = f'{today.microsecond}'[:1]
        current_time = main_time.format(microseconds)
        return current_time

    @classmethod
    def build_cdi_response(cls, seq, code, msg):
        root = ET.Element("message", attrib=dict(module="iCMS", version="1.0"))
        ET.SubElement(root, "header",
                      attrib={"timestamp": cls.gen_utf_time(), "sequence": seq,
                              "componentid": "iCMS_01", "command": "DELIVERY_TASK_DONE",
                              "component-type": "iCMS", "action": "RESPONSE"})
        body = ET.SubElement(root, "body")
        ET.SubElement(body, "result", attrib={"code": str(code), "description": msg})
        rough_string = ET.tostring(root, encoding='UTF-8')
        new_string = minidom.parseString(rough_string).toprettyxml(encoding="UTF-8")
        return new_string
