import base64
import re
from hashlib import md5

from vinetrimmer.objects import AudioTrack, TextTrack, Track, Tracks, VideoTrack
#from vinetrimmer.utils import Cdm
from vinetrimmer.vendor.pymp4.parser import Box


def parse(master, source=None):
    """
    Convert a Variant Playlist M3U8 document to a Tracks object with Video, Audio and
    Subtitle Track objects. This is not an M3U8 parser, use https://github.com/globocom/m3u8
    to parse, and then feed the parsed M3U8 object.

    :param master: M3U8 object of the `m3u8` project: https://github.com/globocom/m3u8
    :param source: Source tag for the returned tracks.

    The resulting Track objects' URL will be to another M3U8 file, but this time to an
    actual media stream and not to a variant playlist. The m3u8 downloader code will take
    care of that, as the tracks downloader will be set to `M3U8`.

    Don't forget to manually handle the addition of any needed or extra information or values.
    Like `encrypted`, `pssh`, `hdr10`, `dv`, e.t.c. Essentially anything that is per-service
    should be looked at. Some of these values like `pssh` and `dv` will try to be set automatically
    if possible but if you definitely have the values in the service, then set them.
    Subtitle Codec will default to vtt as it has no codec information.

    Example:
        tracks = Tracks.from_m3u8(m3u8.load(url))
        # check the m3u8 project for more info and ways to parse m3u8 documents
    """
    if not master.is_variant:
        raise ValueError("Tracks.from_m3u8: Expected a Variant Playlist M3U8 document...")

    # get pssh if available
    # uses master.data.session_keys instead of master.keys as master.keys is ONLY EXT-X-KEYS and
    # doesn't include EXT-X-SESSION-KEYS which is whats used for variant playlist M3U8.
    keys = [x.uri for x in master.session_keys if x.keyformat.lower() == "com.microsoft.playready"]
    pssh = keys[0].split(",")[-1] if keys else None
    # if pssh:
        # pssh = base64.b64decode(pssh)
        # # noinspection PyBroadException
        # try:
            # pssh = Box.parse(pssh)
            
        # except Exception:
            # pssh = Box.parse(Box.build(dict(
                # type=b"pssh",
                # version=0,  # can only assume version & flag are 0
                # flags=0,
                # system_ID=Cdm.uuid,
                # init_data=pssh
            # )))

    return Tracks(
        # VIDEO
        [VideoTrack(
            id_=md5(str(x).encode()).hexdigest()[0:7],  # 7 chars only for filename length
            source=source,
            url=("" if re.match("^https?://", x.uri) else x.base_uri) + x.uri,
            # metadata
            codec=x.stream_info.codecs.split(",")[0].split(".")[0],  # first codec may not be for the video
            language=None,  # playlists don't state the language, fallback must be used
            bitrate=x.stream_info.average_bandwidth or x.stream_info.bandwidth,
            width=x.stream_info.resolution[0],
            height=x.stream_info.resolution[1],
            fps=x.stream_info.frame_rate,
            hdr10=(x.stream_info.codecs.split(".")[0] not in ("dvhe", "dvh1")
                   and (x.stream_info.video_range or "SDR").strip('"') != "SDR"),
            hlg=False,  # TODO: Can we get this from the manifest.xml?
            dv=x.stream_info.codecs.split(".")[0] in ("dvhe", "dvh1"),
            # switches/options
            descriptor=Track.Descriptor.M3U,
            # decryption
            encrypted=bool(master.keys or master.session_keys),
            pssh=pssh,
            # extra
            extra=x
        ) for x in master.playlists],
        # AUDIO
        [AudioTrack(
            id_=md5(str(x).encode()).hexdigest()[0:6],
            source=source,
            url=("" if re.match("^https?://", x.uri) else x.base_uri) + x.uri,
            # metadata
            codec=x.group_id.replace("audio-", "").split("-")[0].split(".")[0],
            language=x.language,
            bitrate=0,  # TODO: M3U doesn't seem to state bitrate?
            channels=x.channels,
            atmos=(x.channels or "").endswith("/JOC"),
            descriptive="public.accessibility.describes-video" in (x.characteristics or ""),
            # switches/options
            descriptor=Track.Descriptor.M3U,
            # decryption
            encrypted=False,  # don't know for sure if encrypted
            pssh=pssh,
            # extra
            extra=x
        ) for x in master.media if x.type == "AUDIO" and x.uri],
        # SUBTITLES
        [TextTrack(
            id_=md5(str(x).encode()).hexdigest()[0:6],
            source=source,
            url=("" if re.match("^https?://", x.uri) else x.base_uri) + x.uri,
            # metadata
            codec="vtt",  # assuming VTT, codec info isn't shown
            language=x.language,
            forced=x.forced == "YES",
            sdh="public.accessibility.describes-music-and-sound" in (x.characteristics or ""),
            # switches/options
            descriptor=Track.Descriptor.M3U,
            # extra
            extra=x
        ) for x in master.media if x.type == "SUBTITLES"]
    )