from manifest_edit.plugin.m3u8_main import BasePlugin
from schema import Schema, Or, Optional
from manifest_edit.context import Context
from manifest_edit.plugins.utility.m3u8_main.ext_x_media_selection import ExtXMediaSelection
import re


class Plugin(BasePlugin):
    """A plugin that can change the default language in hls main manifests

    DEFAULT: (Optional) A string indicating the media selection should be
             played if the user hasn't selected another option. Valid values
             are YES and NO.
    """

    _name = __name__

    _keys = ["default", "autoselect", "characteristics"]

    def schema(self):
        return Schema([
            {
                **ExtXMediaSelection().dictSchema(),
                **{
                    "type": Or("AUDIO", "SUBTITLES"),      # overriding ExtXMediaSelection key to limit to audio/sub track
                    Optional(self._keys[0]): Or("YES", "NO"),     # value to set
                    Optional(self._keys[1]): Or("YES", "NO"),     # value to set
                    Optional(self._keys[2], default=None): str,   # value to set
                }
            }
        ])

    def set_characteristics(self, media, value):
        """
        2.12. If you provide Descriptive Video Service (DVS), also called audio
        description, it MUST be marked with the attribute
        CHARACTERISTICS="public.accessibility.describes-video".

        2.13. If you provide DVS, the AUTOSELECT attribute MUST have a value
        of "YES".

        4.5. If a subtitles track is intended to provide accessibility for
        people who are deaf or hard of hearing, it MUST be marked with the
        attribute CHARACTERISTICS="public.accessibility.describes-spoken-dialog
        ,public.accessibility.describes-music-and-sound".
        (Subtitles with this attribute value are treated the same as closed
        captions.)

        4.6. If a subtitles track is intended to provide accessibility for
        people who are deaf or hard of hearing, the AUTOSELECT attribute MUST
        have a value of "YES".

        The string used for CHARACTERISTICS will be user-provided and no checks
        will be performed.

        If a non-null string is set, AUTOSELECT will be set to YES as well
        """
        media.characteristics = value
        
        if value:
            media.autoselect = "YES"

    def set_autoselect(self, media, value):
        """
        4.3.4.1. EXT-X-MEDIA

          If the AUTOSELECT attribute is present, its value MUST be YES if
            the value of the DEFAULT attribute is YES.

        This method will set the autoselect value. It will not allow turning
        AUTOSELECT off for default tracks
        """
        if value == "YES" or media.default == "NO":
            media.autoselect = value

    def set_default(self, manifest, media, value):
        """
        4.3.4.1.1. Rendition Groups

          A Group MUST NOT have more than one member with a DEFAULT
            attribute of YES.

        4.3.4.1. EXT-X-MEDIA

          If the AUTOSELECT attribute is present, its value MUST be YES if
            the value of the DEFAULT attribute is YES.

        This method will set a media to DEFAULT=YES and will reset the DEFAULT
        to NO for all other medias in the same GROUP-ID and the same TYPE as
        required by the standard.

        If DEFAULT is set to YES, AUTOSELECT is set to YES as well
        """

        if value == "YES":
            media.default = value
            media.autoselect = value
            # reset default for others
            for _m in manifest.medias:
                if (
                    _m is not media
                    and _m.type == media.type
                    and _m.groupId == media.groupId
                ):
                    _m.default = "NO"

        elif value == "NO":
            media.default = value
        else:
            raise NotImplementedError

    def process(self, manifest, storage):
        if not len(manifest.medias):
            Context.log_warning(
                "The provided m3u8 manifest does not have"
                " an EXT-X-MEDIA section! Skipping..."
            )
            return

        for config_item in self.config(storage=storage):

            default_value = config_item.get("default", None)
            autoselect_value = config_item.get("autoselect", None)
            characteristics_value = config_item.get("characteristics") #default is None by config

            for media in ExtXMediaSelection().medias(config_item, manifest):

                if default_value:
                    self.set_default(
                        manifest,
                        media,
                        default_value
                    )

                if autoselect_value:
                    self.set_autoselect(media, autoselect_value)

                # If user has provided an empty string, we will
                # delete the attribute. If it provided nothing,
                # this will be ignored
                if type(characteristics_value) == str:
                    self.set_characteristics(media, characteristics_value)
