#!/usr/bin/env python3

"""
threefive command line SCTE35 decoder.

"""


import sys
from new_reader import reader
from threefive import Cue, Stream, print2, decode, version
from threefive.sixfix import sixfix

REV = "\033[7;1m"
NORM = "\033[27m\033[0m"
NORM = "\033[0m"
BLUE = "\033[36;1;51m"

mapped = {
    "base64": "encode",
    "bytes": "get_bytes",
    "hex": "encode2hex",
    "json": "get_json",
    "int": "encode2int",
    "xml": "xml",
}


def xml_out(cue):
    """
    xml_out prints cue as xml
    """
    print2(cue.xml())


class SupaStream(Stream):
    """
    SupaStream is subclass of Stream used
    to print raw SCTE-35 packets.
    """


    def _parse_scte35(self, pkt, pid):
        print2(pkt)
        super()._parse_scte35(pkt, pid)


def mk_sidecar(cue):
    """
    mk_sidecar generates a sidecar file with the SCTE-35 Cues
    """
    pts = 0.0
    with open("sidecar.txt", "a") as sidecar:
        cue.show()
        if cue.packet_data.pts:
            pts = cue.packet_data.pts
        data = f"{pts},{cue.encode()}\n"
        sidecar.write(data)


HELP = f"""
{REV}     Parse         {NORM}

    {BLUE}    base64: {NORM}\tthreefive '/DAWAAAAAAAAAP/wBQb+AKmKxwAACzuu2Q=='
    {BLUE}    hex: {NORM}\t\tthreefive '0xfc301600000000000000fff00506fe00a98ac700000b3baed9'
    {BLUE}    files: {NORM}\t\tthreefive myvideo.ts
    {BLUE}    stdin: {NORM}\t\tcat myvideo.ts | threefive
    {BLUE}    http(s): {NORM}\tthreefive https://futzu.com/xaa.ts
    {BLUE}    udp: {NORM}\t\tthreefive udp://127.0.0.1:3535
    {BLUE}    multicast:{NORM}\tthreefive udp://@235.35.3.5:3535

{REV}    Keywords      {NORM}

   {REV} sixfix   {NORM}{BLUE}\tFix SCTE-35 data mangled by ffmpeg:{NORM} threefive sixfix video.ts

   {REV} xml      {NORM}{BLUE}\tParse a SCTE-35 Cue string or mpegts stream and output xml: {NORM}

     {BLUE}\tParse base64 SCTE-35 string and output xml: {NORM} threefive xml'/DAWAAAAAAAAAP/wBQb+AKmKxwAACzuu2Q=='
     {BLUE}\tParse a mpegts stream for scte35 and output xml: {NORM} threefive xml video.ts

   {REV} packets {NORM}{BLUE}\tPrint raw SCTE-35 packets from mpegts video:{NORM} threefive packets video.ts

   {REV} show    {NORM}{BLUE}\tProbe mpegts video:{NORM}     threefive show video.ts

   {REV} pts     {NORM}{BLUE}\tPrint PTS from mpegts video:{NORM}    threefive pts video.ts

   {REV} proxy   {NORM}{BLUE}\tParse a stream, write raw video to stdout:{NORM} threefive proxy https://example.com/video.ts

   {REV} sidecar {NORM}{BLUE}\tParse a stream, write pts,write SCTE-35 Cues to sidecar.txt:{NORM}  threefive sidecar https://example.com/video.ts

   {REV} encode  {NORM}{BLUE}\tLoad JSON, XML, Base64 or Hex and encode to JSON,XML,Base64,Hex,Int or Bytes:{NORM}

    {BLUE}\tLoad JSON to base64:{NORM}  threefive encode < json.json
    {BLUE}\tLoad JSON to hex:{NORM} threefive encode hex  < json.json
    {BLUE}\tLoad JSON to xml:{NORM}  threefive encode xml < json.json

    {BLUE}\tLoad xml to hex:{NORM}  cat xml.xml | threefive encode hex
    {BLUE}\tLoad xml to base64:{NORM}  threefive encode  < xml.xml
    {BLUE}\tLoad xml to json:{NORM}  cat xml.xml | threefive encode json

    {BLUE}\tBase64 to bytes:{NORM} threefive encode bytes  '/DAlAAAAAAAAAP/wFAUAAAAOf+/+FOvVwP4ApMuAAA4AAAAAzBon0A=='
    {BLUE}\tBase64 to hex:{NORM} threefive encode hex  '/DAlAAAAAAAAAP/wFAUAAAAOf+/+FOvVwP4ApMuAAA4AAAAAzBon0A=='
    {BLUE}\tBase64 to xml:{NORM} threefive encode xml  '/DAlAAAAAAAAAP/wFAUAAAAOf+/+FOvVwP4ApMuAAA4AAAAAzBon0A=='

    {BLUE}\tHex to base64:{NORM} threefive encode base64 0xfc302500000000000000fff014050000000e7feffe14ebd5c0fe00a4cb80000e00000000cc1a27d0
    {BLUE}\tHex to xml:{NORM} threefive encode xml 0xfc302500000000000000fff014050000000e7feffe14ebd5c0fe00a4cb80000e00000000cc1a27d0
    {BLUE}\tHex to int:{NORM} threefive encode int 0xfc302500000000000000fff014050000000e7feffe14ebd5c0fe00a4cb80000e00000000cc1a27d0

  {REV} version {NORM}{BLUE}\tShow version:{NORM} threefive version

  {REV} Help    {NORM} {BLUE}\tHelp:{NORM}  threefive help
"""


def print_help():
    """
    print_help checks sys.argv for the word help
    and displays the help if found
    """
    print2(HELP)
    sys.exit()


def print_version():
    """
    version_chk checks for the version keyword.

    """
    print2(f"{version}")
    sys.exit()


def json_load():
    """
    json_load is used by encode
    """
    cmdlist = list(mapped.keys()) + ["encode"]
    json = False
    arglist = [arg for arg in sys.argv[1:] if arg not in cmdlist]
    if not arglist:
        with reader(sys.stdin.buffer) as stuff:
            json = stuff.read().decode()
            arglist.append(json)
    for that in arglist:
        try:
            cue = Cue()
            cue.load(that)
        except:
            try:
                cue = Cue(that)
                cue.decode()
            except:
                print2("threefive accepts json, xml, base64, or hex as input")
                return False
        cue.encode()
        for k, v in mapped.items():
            if k in sys.argv:
                method = getattr(cue, v)
                print2(method())
                sys.exit()
        print(cue.encode())
        sys.exit()


print_map = {
    "help": print_help,
    "version": print_version,
    "encode": json_load,
}


#   #   #


def no_op(cue):
    """
    no_op is just a dummy func to pass to Stream.decode()
    to suppress output.
    """
    return cue


def packet_chk(this):
    """
    packet_chk checks for the packet keyword
    and displays SCTE-35 packets if present.
    """
    supa = SupaStream(this)
    supa.decode()


def proxy_chk(this):
    """
    proxy_chk checks for the proxy keyword
    and proxies the stream to stdout if present.
    proxy_chk also writes pts,cue pairs to sidecar.txt
    """
    strm = Stream(this)
    strm.proxy(func=mk_sidecar)


def pts_chk(this):
    """
    pts_chk is used to display PTS.
    """
    strm = Stream(this)
    strm.show_pts()


def show_chk(this):
    """
    show_chk checks for the show keyword
    and displays the streams if present.
    """
    strm = Stream(this)
    strm.show()


def sidecar_chk(this):
    """
    sidecar_chk checks for the sidecar keyword and
    generates a sidecar file if present.
    """
    strm = Stream(this)
    strm.decode(func=mk_sidecar)


def to_xml(this):
    """
    to_xml prints cues as xml instead of json.
    """
    try:
        # Mpegts Video
        strm = Stream(this)
        strm.decode(func=xml_out)
        return True

    except:
        try:
            cue = Cue(this)
            cue.decode()
            print2(cue.xml())
            return True
        except:
            return False


func_map = {
    "pts": pts_chk,
    "show": show_chk,
    "packets": packet_chk,
    "proxy": proxy_chk,
    "sidecar": sidecar_chk,
    "xml": to_xml,
    "sixfix": sixfix,
}


def chk_print_map():
    """
    chk_print_map checks for print_map.keys() in sys.argv
    """
    for k, v in print_map.items():
        if k in sys.argv:
            v()
            sys.exit()


def chk_func_map():
    """
    chk_func_map checks for func_map.keys() in sys.argv
    """
    for k, v in func_map.items():
        if k in sys.argv:
            args = [arg for arg in sys.argv[1:] if arg not in func_map]
            for mo in args:
                v(mo)
            sys.exit()


if __name__ == "__main__":
    if len(sys.argv) > 1:
        chk_print_map()
        chk_func_map()
        for arg in sys.argv[1:]:
            decode(arg)
    else:
        decode(sys.stdin.buffer)
