"""
This package contains functionalities that are specific to .m3u8 (HLS)
manifest manipulation.

It contains data types that represent elements and attributes of a "Master"
or "Main" playlist as well as for "Media" playlists as described by
`RFC 8216 <https://tools.ietf.org/html/rfc8216>`__.

When working with libfmp4.hls, you abstract from the actual textual
representation format of the manifest and manipulate directly
native python types representing a manifest's properties and elements.

At the moment, manifest-edit.libfmp4 does not expose to python any supported
serialization or deserialization methods, i.e. you cannot load and parse an
.m3u8 file to a libfmp4.hls.Manifest data type or dump a libfmp4.hls Manifest
object to a file. Its main purpose is to be used within the manifest-edit
application that has explicit entrypoints to receive and return
libfmp4.hls.Manifest or Playlist objects to/from an external applications. All
methods included in this library to render objects to strings are only to be
used for debug purposes and are not suited to produce a legal textual
representation of a manifest or any of its parts.

It is worth remembering this package's naming convention:

 - free functions use lower snake case (e.g. my_function)
 - class names use upper CamelCase convention (e.g. MyClass)
 - class attributes use lower camelCase convention (e.g. myAttribute).

In order to improve the usability of this library to people familiar with
the syntax of an .m3u8 manifest, some basic mnemonic rules can be used to
infer where in the libfmp4.hls.Manifest and libfmp4.hls.Playlist types
each element of a manifest is stored. In particular:

 - m3u8 attributes named <XXX>-<YYY> are conventionally stored in <xxxYyy>
   class attributes (i.e. the 'INSTREAM-ID' attribute of a media is stored
   in the 'instreamId' attribute of the Media class).

 - members of Manifest or Playlist storing the content of entire TAGS
   (i.e. 'EXT-X-I-FRAME-STREAM-INF') do not qualify for a simple and
   non-ambiguous mnemonic name conversion. For this reason, the methods
   `getByTag` and `setByTag` can be used as getters/setters to access the
   member through the tag name. An example is the `hlsSignalingDatas` member,
   holding information that in the manifest are reported under the
   `EXT-X-SESSION-KEY` tag. It is possible to write/read to this field by
   using both the `manifest.hlsSignalingDatas` attribute and by using the
   getter `manifest.getByTag('EXT-X-SESSION-KEY')`.

"""

import sys

from manifest_edit.libfmp4.utility import (
    _get_member_by_tag,
    _set_member_by_tag
  )

# import everything from libfmp4.hls
from libfmp4.hls import *  # noqa: F403

_MANIFEST_TAGS_MAP = {
    "EXT-X-VERSION": "version",
    "EXT-X-INDEPENDENT-SEGMENTS": "independentSegments",
    "EXT-X-MEDIA": "medias",
    "EXT-X-STREAM-INF": "streams",
    "EXT-X-I-FRAME-STREAM-INF": "iFrameStreams",
    "EXT-X-SESSION-KEY": "hlsSignalingDatas",
    "EXT-X-PLAYREADYHEADER": "playreadyHeader",
    # #EXT-X-DXDRM:      ??
    # #EXT-X-DXDRMINFO:  ??
}
setattr(Manifest, "TAGS_MAP", _MANIFEST_TAGS_MAP)
setattr(Manifest, "getByTag", _get_member_by_tag)
setattr(Manifest, "setByTag", _set_member_by_tag)

_STREAMINF_TAGS_MAP = {
    "BANDWIDTH": "bandwidth",
    "AVERAGE-BANDWIDTH": "averageBandwidth",
    "CODECS": "codecs",
    "RESOLUTION": "resolution",
    "FRAME-RATE": "frameRate",
    "VIDEO-RANGE": "videoRange",
    "HDCP-LEVEL": "hdcpLevel",
    "URI": "uri",
    # GROUPS?
}

setattr(StreamInf, "TAGS_MAP", _STREAMINF_TAGS_MAP)
setattr(StreamInf, "getByTag", _get_member_by_tag)
setattr(StreamInf, "setByTag", _set_member_by_tag)

_MEDIA_TAGS_MAP = {
    "TYPE": "type",
    "SUBFORMAT": "subFormat",
    "URI": "uri",
    "GROUP-ID": "groupId",
    "LANGUAGE": "language",
    "NAME": "name",
    "DEFAULT": "default",
    "AUTOSELECT": "autoselect",
    "FORCED": "forced",
    "INSTREAM-ID": "inStreamId",
    "CHARACTERISTICS": "characteristics",
    "CHANNELS": "channels",
    # USP-X-MEDIA
    "BANDWIDTH": "bandwidth",
    "AVERAGE-BANDWIDTH": "averageBandwidth",
    "CODECS": "codecs",
    "RESOLUTION": "resolution",
    "FRAME-RATE": "frameRate",
    "VIDEO-RANGE": "videoRange",
    "HDCP-LEVEL": "hdcpLevel",
}

setattr(Media, "TAGS_MAP", _MEDIA_TAGS_MAP)
setattr(Media, "getByTag", _get_member_by_tag)
setattr(Media, "setByTag", _set_member_by_tag)

_EXTINF_TAGS_MAP = {
    "EXT-X-BYTE-RANGE": "byteRange",
    "EXT-X-DISCONTINUITY": "discontinuity",
    "EXT-X-KEY": "keys",
    "EXT-X-PROGRAM-DATE-TIME": "programDateTime",
    "EXT-X-GAP": "gap",
    "EXT-X-DATERANGE": "dateRanges",
}

setattr(ExtInf, "TAGS_MAP", _EXTINF_TAGS_MAP)
setattr(ExtInf, "getByTag", _get_member_by_tag)
setattr(ExtInf, "setByTag", _set_member_by_tag)
