import sys, os, urllib2, re, requests
#CLI_MODE = True
from kodiswift import xbmc, xbmcgui, CLI_MODE
from kodiswift import Plugin, storage
from resources.lib.content import util, ContentSources
#from resources.lib.content import Downloader
#from twisted.web import client
#from twisted.internet import reactor, defer

#plugin = Plugin()
#plugin.load_addon_settings()
#playlist = plugin.get_setting("general_playlist",str)
#proxy_url = plugin.get_setting("general_proxy_url",str)

cunicode = lambda s: s.decode("utf8") if isinstance(s, str) else s
cstr = lambda s: s.encode("utf8") if isinstance(s, unicode) else s

cmd = sys.argv[1]
title = sys.argv[2]
data = sys.argv[3]
download_dir = sys.argv[4]

cur_directory = os.path.dirname(__file__)
sources_directory = os.path.join(cur_directory,"resources","lib", "content", "sources")
sources = ContentSources.ContentSources(sources_directory)

def main():
    if not sources.is_video(data):
        print "It is not video link"
        notify("It is not video link")
        sys.exit(1)

    streams = sources.get_streams(data)

    if not CLI_MODE:
        ret = 0
        #ret = xbmcgui.Dialog().select("Select stream",streams) # TODO
    else:
        ret = 0
    stream = streams[ret]
    #output =  stream["name"].replace("\\"," ").replace(":"," ").replace("|"," ")
    output = re.sub("[\\/\n\r\t,:\?\|'~\.]","_",title)
    if isinstance(output, str):
        output = output.decode("utf8")

    for sub in stream["subs"]:
        suburl = sub["url"]
        slang = "_" + sub["lang"] if sub["lang"] else ""
        download_sub(suburl, output+slang)

    if "nfo" in stream and stream["nfo"]:
        nfofile = os.path.join(download_dir, output+".nfo")
        with open(nfofile,"w") as f:
            nfo_txt = util.nfo2xml(stream["nfo"])
            f.write(nfo_txt)

    download_video(stream["url"], os.path.join(download_dir, output), stream["headers"])

    #d = Downloader.download_video(stream["url"], os.path.join(download_dir, output), stream["headers"])
    #reactor.run()


    #xbmcgui.Dialog().ok("Info","Start download")

    #mode = "a" if os.path.exists("context_menu.log") else "w"
    #with open("context_menu.log", mode) as f:
    #    f.write("%s %s %s %s", sys.argv[1], sys.argv[2], sys.argv[3], sys.argv[4])


def download_video(url,output,headers=None):
    #output = stream["name"].replace("\\"," ").replace(":"," ").replace("|"," ")
    if not headers:
        headers = {"user-agent":"Enigma2"}
    try:
        h = get_header(url,headers=headers)
        mtype = h.get("content-type")
        ext,stream_type = get_ext(mtype)
    except Exception as e:
        ext,stream_type = (".ts","hls")
    output = output+ext
    if stream_type == "hls":
        download_hls(url, output, headers=headers)
    else:
        download_file(url, output, headers=headers)


def download_hls(url, title, download_dir="", headers=None, overwrite=True, limit=None):
    UA = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"
    if not headers:
        headers = {"User-Agent" : UA}
    key = headers["key"] if "key" in headers else ""
#    if not "User-Agent" in headers:
#        headers["User-Agent"] = UA
    tsname = os.path.join(download_dir,title)

    notify("Download started - %s" % title)
    print "Start download"
    print url
    try:
        r = requests.get(url,headers=headers)
    except Exception as e:
        raise Exception("Cannot open manifsest file - %s"%url)
    if not r.content.startswith("#EXTM3U"):
        raise Exception("Not valid manifest file - %s" % url)
    streams = re.findall(r"#EXT-X-STREAM-INF:.*?BANDWIDTH=(\d+).*?\n(.+?)$", r.content, re.IGNORECASE | re.MULTILINE)
    i = 0
    while streams:
        if i > 4: break
        sorted(streams, key=lambda item: int(item[0]), reverse=True)
        base_url = "/".join(url.split("?")[0].split("/")[:-1])+"/"
        url = streams[0][1]
        if not url.startswith("http"):
            url = base_url + url
        print url
        try:
            r = requests.get(url, headers=headers)
        except Exception as e:
            raise Exception("Cannot open manifsest file - %s"%url)
        i += 1
        streams = re.findall(r"#EXT-X-STREAM-INF:.*?BANDWIDTH=(\d+).*?\n(.+?)$", r.content, re.IGNORECASE | re.MULTILINE)
    ts_list = re.findall(r"#EXTINF:([\d\.]+),.*?\n(.+?)$", r.content, re.IGNORECASE | re.MULTILINE)
    base_url = "/".join(url.split("/")[:-1])+"/"

    if not len(ts_list):
        raise Exception("Cannot read fragment list in  manifsest file - %s"%url)

    ts_num = 0
    type = "vod" if "#EXT-X-ENDLIST" in r.content else "live"
    currentbytes = 0.0
    totalbytes = -1
    currenttime = 0.0
    totaltime = sum(map(float,zip(*ts_list)[0]))
    #ts_file = open(outputfile, "wb")

    if isinstance(tsname, str):
        tsname = tsname.decode("utf8")
    tsfile = open(tsname,"wb")
    for ts in ts_list:
        url2 = ts[1]
        #print "Downloading ", url2
        #fname = os.path.join(download_dir,url2.split("/")[-1])
        if not url2.startswith("http"):
            url2 = base_url + url2

        r = requests.get(url2, headers=headers, verify=False)
        content = r.content
        if key:
            from Crypto.Cipher import AES
            key2 = binascii.a2b_hex(key)
            iv = content[:16]
            d = AES.new(key2, AES.MODE_CBC, iv)
            content = d.decrypt(content[16:])
        #with open(fname,"wb") as f:
            #f.write(content)
        tsfile.write(content)

        content_length = len(content)
        currentbytes += content_length
        currenttime += float(ts_list[ts_num][0])
        totalbytes = currentbytes * totaltime / currenttime
        ts_num += 1
        #print "Fragment %s downloaded (%s)"%(self.ts_num,len(content))
        progress = float(currentbytes)/float(totalbytes)*100
        print "%.1f%% (%i/%i)"%(progress,currentbytes,totalbytes)

        if type == "vod":
            if ts_num >= len(ts_list) or (limit and currenttime>limit):
                break
        else:
            if limit and currenttime>limit: # TODO
                break

    print "Finished"
    notify("Download finished - %s" % title)

    tsfile.close()


def download_file(url, title, download_dir="", headers=None, overwrite=True, limit=None):
    UA = "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:51.0) Gecko/20100101 Firefox/51.0"
    if not headers:
        headers = {"User-Agent" : UA}
    key = headers["key"] if "key" in headers else ""
#    if not "User-Agent" in headers:
#        headers["User-Agent"] = UA
    fname = os.path.join(download_dir,title)
    if isinstance(fname, str):
        fname = fname.decode("utf8")

    notify("Download started - %s" % title)
    print "Start download"
    print url
    try:
        r = requests.get(url,headers=headers, stream=True)
    except Exception as e:
        raise Exception("Cannot open url - %s"%url)
    currentbytes = 0.0
    totalbytes = int(r.headers["content-length"])

    with open(fname, 'wb') as fd:
        for chunk in r.iter_content(chunk_size=1024*1024):
            fd.write(chunk)
            currentbytes += len(chunk)
            progress = float(currentbytes)/float(totalbytes)*100
            print "%.1f%% (%i/%i)"%(progress,currentbytes,totalbytes)

    print "Finished"
    notify("Download finished - %s" % title)

def download_sub(suburl, output):
    try:
        subs = urllib2.urlopen(suburl).read()
    except:
        subs = None
    if subs:
        if ".xml" in suburl:
            subs = util.ttaf2srt(subs)
            subext = ".srt"
        elif ".vtt" in suburl:
            subext = ".vtt"
        elif ".srt" in suburl:
            subext = ".srt"
        else:
            subext = ""
        if subext:
            subfile = cunicode(os.path.join(download_dir, output+subext))
            with open(subfile,"w") as f:
                f.write(subs)
    else:
        print "\n Error downloading subtitle %s"%suburl



def get_header(url,headers=None):
    r = requests.head(url,headers=headers)
    return r.headers

def get_ext(mtype):
    stype = "http"
    if mtype in ("vnd.apple.mpegURL","application/x-mpegURL",'application/x-mpegurl',"application/vnd.apple.mpegurl"):
        return ".ts","hls"
    elif mtype in ("application/dash+xml"):
        return ".ts","dash" # TODO dash stream type  could be different !
    elif mtype in ("video/mp4"):
        return ".mp4","http"
    elif mtype in ("video/MP2T","video/mp2t"):
        return ".ts","http"
    elif mtype in ("video/x-flv"):
        return ".flv","http"
    elif mtype in ("video/quicktime"):
        return ".mov","http"
    elif mtype in ("video/x-msvideo"):
        return ".avi","http"
    elif mtype in ("video/x-ms-wmv"):
        return ".wmv","http"
    elif mtype in ("video/x-matroska"):
        return ".mkv","http"
    else:
        return ".mp4","http"


def notify(text, title="Info", time=10000):
    if isinstance(text, unicode):
        text = text.encode("utf8")
    #xbmc.executebuiltin('Notification(Hello World,This is a simple example of notifications,5000,/script.hellow.world.png)')
    xbmc.executebuiltin('Notification(%s, %s, %d, %s)'%("Info", text, time, xbmcgui.NOTIFICATION_INFO))

if __name__ == '__main__':
    main()
