# -*- coding: utf-8 -*-
################################################################################
#				yt.py - Teil von Kodi-Addon-ARDundZDF
#	vorherige pytube-library von Nick Ficano (nficano) wieder entfernt
# 	(https://github.com/nficano/pytube) - für die frei zugänglichen
#	phoenix-Videos entfällt die Dechiffrierung der Youtube-Signaturen.
#	Damit entfallen auch Importprobleme und die laufende Anpassung an
#	die pytube-library.
#	Test-Videos: Rubriken/Bundestag
#
#	März 2022: ergänzt mit MediathekViewWeb-Funktionen, basierend auf
#		dem api von Dev. bagbag (https://github.com/bagbag), 
#		https://github.com/mediathekview/mediathekviewweb,
#		https://mediathekview.de/news/mediathekviewweb/,
#		https://github.com/mediathekview 
#
#	April 2023: phoenix-Youtube-Videos nicht mehr zugänglich, phoenix-
#		Modul umgestellt auf ARD-new-Funktionen. Youtube-Funktionen
#		yt_get und get_stream_details vorerst nicht mehr genutzt,
#		11.01.2026 beide Funktionen entfernt.
#
################################################################################
#
#	17.03.2020 Kompatibilität Python2/Python3: Modul future, Modul kodi-six
#	
# 	<nr>10</nr>								# Numerierung für Einzelupdate
#	Stand: 11.01.2026
#

from __future__ import absolute_import

from kodi_six import xbmc, xbmcaddon, xbmcplugin, xbmcgui, xbmcvfs
# o. Auswirkung auf die unicode-Strings in PYTHON3:
from kodi_six.utils import py2_encode, py2_decode

import os, sys
PYTHON2 = sys.version_info.major == 2
PYTHON3 = sys.version_info.major == 3
if PYTHON2:
	from urllib import quote, unquote, quote_plus, unquote_plus, urlencode, urlretrieve
	from urllib2 import Request, urlopen, URLError 
	from urlparse import urljoin, urlparse, urlunparse, urlsplit, parse_qs
elif PYTHON3:
	from urllib.parse import quote, unquote, quote_plus, unquote_plus, urlencode, urljoin, urlparse, urlunparse, urlsplit, parse_qs
	from urllib.request import Request, urlopen, urlretrieve
	from urllib.error import URLError
	try:									# https://github.com/xbmc/xbmc/pull/18345 (Matrix 19.0-alpha 2)
		xbmc.translatePath = xbmcvfs.translatePath
	except:
		pass


import ardundzdf					# -> test_downloads, Main, start_script, build_Streamlists_buttons
from resources.lib.util import *

ICON_MEHR 		= "icon-mehr.png"
ICON_DIR_WATCH	= "Dir-watch.png"

ADDON_ID      	= 'plugin.video.ardundzdf'
SETTINGS 		= xbmcaddon.Addon(id=ADDON_ID)
ADDON_NAME    	= SETTINGS.getAddonInfo('name')
SETTINGS_LOC  	= SETTINGS.getAddonInfo('profile')
ADDON_PATH    	= SETTINGS.getAddonInfo('path')	# Basis-Pfad Addon
ADDON_VERSION 	= SETTINGS.getAddonInfo('version')
PLUGIN_URL 		= sys.argv[0]				# plugin://plugin.video.ardundzdf/
HANDLE			= int(sys.argv[1])
NAME			= 'ARD und ZDF'

# 11.01.2026 ergänzt: description (zusätzlich zu title, topic), future=true (vorher false), s. 
#	https://github.com/rols1/Kodi-Addon-ARDundZDF/issues/49
MVW_DATA_ALL 	= '{"queries":[{"fields":["title","topic","description"],"query":"%s"}],"sortBy":"timestamp","sortOrder":"desc","future":true,"offset":%d,"size":%d}'
MVW_DATA = '{"queries":[{"fields":["channel"],"query":"%s"},{"fields":["channel","topic","title","description"],"query":"%s"}],"sortBy":"timestamp","sortOrder":"desc","future":true,"offset":%d,"size":%d}'

#----------------------------------------------------------------
# 19.12.2020 ytplayer.config nicht mehr vor itag's positioniert - Block-
#	bildung direkt mit itag (s.u.)
# 11.01.2026 yt_get, get_stream_details und get_duration entfernt
# def yt_get(url, vid, title, tag, summ, thumb):
# def get_stream_details(stream):
# get_duration(page):	
# ----------------------------------------------------------------------
	
##################### MediathekViewWeb-Funktionen ######################
# Aufruf aus den div. Hauptmenüs (Setting pref_use_mvw)
# Web: mediathekviewweb.de
# func-Bsp. (Fallback bei Absturz nach Sofortstart-Abbruch): 
#	resources.lib.ARDnew.Main_NEW
#
def MVWSearch(title, sender, offset=0, query='', home_id='', myfunc=''):
	PLog('MVWSearch:') 
	PLog(title); PLog(sender); PLog(offset); PLog(query); 
	PLog(home_id); PLog(myfunc);
		
	if sender == '':								# Sender gewählt?
		CurSender = Dict("load", 'CurSender')		
		sendername, sender, kanal, img, az_sender = CurSender.split(':')
	PLog(sender)
	
	if query == '':
		query = get_keyboard_input() 
		if query == None or query.strip() == '': 	# None bei Abbruch
			# return								# Absturz nach Sofortstart-Abbruch					
			if myfunc == '':
				myfunc = ardundzdf.Main 
			import importlib
			fparams="{}"  
			fparams = quote(fparams)
			ardundzdf.start_script(myfunc, fparams, is_dict=False)	# Fallback zu myfunc
			return									# ohne return wird hier fortgesetzt
			
	query = query.strip()
	query_org = query
	lsize = 20								# Anzahl pro Liste
	offset=int(offset)
	 
	PLog("Mark0")
	if "ARD|ZDF" in sender:					# Suche in ARD und ZDF
		data = MVW_DATA_ALL  % (query, offset, lsize)
	else:									# Suche in einz. Sender / Channel
		data = MVW_DATA % (sender, query, offset, lsize)
	PLog("data: " + data)
	
	page, msg = get_mvw_page(data)
	if page == '':	
		msg1 = "Fehler in MVWSearch:"
		msg2 = msg
		MyDialog(msg1, msg2, '')	
		return
		
	PLog(type(page))
	page = json.dumps(page)					# tuple -> string
	page = transl_json(page)
	
	page = page.replace('\\"', '"')			# dumps-doublequotes
	page = page.replace('\\"', '*')			# doublequotes			
	#RSave('/tmp2/x_MVW.json', py2_encode(page)) # Debug
	
	items = blockextract('"channel"', page)
	queryInfo = stringextract('"queryInfo"', '"err"', page)	
	PLog(len(items))
	if len(items) == 0:	
		msg1 = u"Suchwort >%s< leider nicht gefunden" % py2_decode(query)
		MyDialog(msg1, '', '')	
		return	
		
	li = xbmcgui.ListItem()
	if home_id:
		li = home(li, home_id)				# Home-Button
	else:
		li = home(li, NAME)					# Hauptmenü
	
	mediatype=''
	if SETTINGS.getSetting('pref_video_direct') == 'true':	# Sofortstart?
		mediatype='video'
	
	PLog("Mark0")
	try:
		mark = query
		img = R("suche_mv.png"); cnt=0
		page = py2_decode(page)
		page = transl_json(page)
		Results = stringextract('"totalResults":', '}', page)	# 100,"totalRelation":"eq","totalEntries":68411
		totalResults = Results.split(",")[0]	
		PLog(totalResults)
		totalResults = int(totalResults)
	except Exception as exception:
		totalResults=1										# trotzdem Fortsetzung, ohne Mehr-Button, s.u.
		PLog("MVWSearch_error: " + str(exception))
	
	for item in items:
		channel 	= stringextract('"channel":"', '"', item)
		topic 		= stringextract('"topic":"', '"', item)
		title 		= stringextract('"title":"', '"', item)
		title 		= make_mark(mark, title, "", bold=True)	# farbige Markierung
		
		descr 		= stringextract('"description":"', '"', item)
		timestamp 	= stringextract('"timestamp":', ',', item)
		duration 	= stringextract('"duration":', ',', item)
		size 		= stringextract('"size":', ',', item)
		url_website	= stringextract('"url_website":"', '"', item)
		sended 		= stringextract('"filmlisteTimestamp":"', '"', item)
		sid 		= stringextract('"id":"', '"', item)
		
		url_sub 	= stringextract('"url_subtitle":"', '"', item)
		url_med 	= stringextract('"url_video":"', '"', item)		# med?
		url_low 	= stringextract('"url_video_low":"', '"', item)
		url_hd 		= stringextract('"url_video_hd":"', '"', item)

		PLog(timestamp); PLog(sended);
		tstamp = datetime.datetime.fromtimestamp(int(timestamp))
		tstamp = tstamp.strftime("%d. %b. %Y %R")
		if sended:
			sended = datetime.datetime.fromtimestamp(int(sended))
			sended = sended.strftime("%d. %b. %Y %R")
			tstamp = py2_decode(tstamp); sended = py2_decode(sended)
		
		dauer="?"
		if duration != '""':										# z.B. Livestream 
			dauer = seconds_translate(duration)
						
		descr = transl_json(descr); 
		summ = repl_json_chars(descr)
		title = transl_json(title)
		descr = transl_json(descr); 
		title = repl_json_chars(title)
		summ = repl_json_chars(descr)
		
		ut = u"nein"
		if url_sub:
			ut = u"ja"
		tag = u"Dauer: %s | [B]%s[/B] | am: [B]%s[/B] | [B]%s[/B] | UT: %s | Filmliste: %s" % \
			(dauer, channel, sended, topic, ut, tstamp)
		tag = repl_json_chars(tag)
		Plot = "%s||||%s" % (tag, summ)
		
		PLog("Satz2:")
		PLog(title); PLog(url_med); PLog(Plot[:80]); PLog(url_sub)		
		
		title=py2_encode(title); Plot=py2_encode(Plot);
		url_sub=py2_encode(url_sub); url_low=py2_encode(url_low); 
		url_med=py2_encode(url_med); url_hd=py2_encode(url_hd)
		fparams="&fparams={'title': '%s','Plot': '%s','home_id': '%s','url_sub': '%s','url_low': '%s','url_med': '%s','url_hd': '%s'}" %\
			(quote(title),quote(Plot),home_id,quote(url_sub),quote(url_low),quote(url_med),quote(url_hd))
		addDir(li=li, label=title, action="dirList", dirID="resources.lib.yt.MVWSingleVideo",
			fanart=img, thumb=img, fparams=fparams, tagline=tag, summary=summ, mediatype=mediatype)
		cnt=cnt+1	
	
	PLog(offset); PLog(lsize)										# Mehr-Button
	new_offset = offset + lsize
	PLog("new_offset: %d" % offset)	
	li = xbmcgui.ListItem()											# Kontext-Doppel verhindern
	if new_offset < totalResults:
		title = "Mehr zu: [B]%s[/B]" % query
		tag = "weiter ab  %d | gesamt: %d" % (new_offset+1, totalResults)
		fparams="&fparams={'title': '%s','sender': '%s','offset': '%s','query': '%s','home_id': '%s','myfunc': '%s'}" %\
			(quote(title),sender,str(new_offset),quote(query),home_id,quote(myfunc))
		addDir(li=li, label=title, action="dirList", dirID="resources.lib.yt.MVWSearch",
			fanart=img, thumb=R(ICON_MEHR), fparams=fparams, tagline=tag)

	title = u"Merkliste -> MVW-Suche %s: [B]%s[/B]" % (sender,query)# Merkliste-Button	
	tag = "[B]Button für die Merkliste via Kontextmenü[/B]"
	summ = u"%s (ab Suchindex 1).\n\n" % title
	summ = u"%sZur Nutzung in der Merkliste bitte den Button via Kontextmenü hinzufügen" % summ
	fparams="&fparams={'title': '%s','sender': '%s','offset': '%s','query': '%s','home_id': '%s','myfunc': '%s'}" %\
		(quote(title),sender,str(0),quote(query),home_id,quote(myfunc))
	addDir(li=li, label=title, action="dirList", dirID="resources.lib.yt.MVWSearch",
		fanart=img, thumb=R(ICON_DIR_WATCH), fparams=fparams, tagline=tag, summary=summ)

	xbmcplugin.endOfDirectory(HANDLE, cacheToDisc=True)
	
# ----------------------------------------------------------------------
# Aufruf: MVWSearch
# Fertigung der Videolisten - bisher nur MP4-Formate gefunden
# 	-> build_Streamlists_buttons (mit opt. Sofortstart)
# url_med: Stammhalter für url_video in den Quellen (alle Werte)
# einz. url-keys können leer sein
def MVWSingleVideo(title,Plot,home_id,url_sub='',url_low='',url_med='',url_hd=''):
	PLog('MVWSingleVideo:')
	PLog(url_sub) 

	HLS_List=[]; MP4_List=[]; HBBTV_List=[];
	track_add = "MediathekView"
	if url_low:
		title_url = u"%s#%s" % (title, url_low)			# low ohne Detailprüfung
		item = u"MP4, %s | %s ** Auflösung %s ** %s" %\
			(track_add, "LOW", "480x270", title_url)
		MP4_List.append(item)
		PLog("item: " + item)
	if url_med:											# key url_video, alle Werte möglich
		res, mark = mvw_get_res(url_med)
		if res == "":									# Fallback SD
			res="720x406"; mark="SD"
		title_url = u"%s#%s" % (title, url_med)
		item = u"MP4, %s | %s ** Auflösung %s ** %s" %\
			(track_add, mark, res, title_url)
		MP4_List.append(item)
		PLog("item: " + item)
	if url_hd:
		res, mark = mvw_get_res(url_hd)
		if res == "":									# Fallback HD
			res="1280x720"; mark="HD"
		title_url = u"%s#%s" % (title, url_hd)
		item = u"MP4, %s | %s ** Auflösung %s ** %s" %\
			(track_add, mark, res, title_url)
		MP4_List.append(item)
		PLog("item: " + item)
	
	ID="MVW"	
	PLog("MP4_List: " + str(len(MP4_List)))
	Dict("store", '%s_HLS_List' % ID, HLS_List) 
	Dict("store", '%s_MP4_List' % ID, MP4_List) 
	Dict("store", '%s_HBBTV_List' % ID, HBBTV_List) 
	
	li = xbmcgui.ListItem(); thumb = R("suche_mv.png")
	geoblock=''; sub_path=url_sub; HOME_ID=home_id
	ardundzdf.build_Streamlists_buttons(li,title,thumb,geoblock,Plot,sub_path,\
		HLS_List,MP4_List,HBBTV_List,ID,HOME_ID)

	xbmcplugin.endOfDirectory(HANDLE, cacheToDisc=True)

# ----------------------------------------------------------------------
# Aufruf MVWSingleVideo mit url_med.
# Auflösung aus den Url-Markierungen ermitteln. MVW-api ohne width*height.
#	Unterschiedliche Markierungen bei den Sendern. json-keys in MVW-
#	Quellen (url_video, url_video_low, url_video_hd) nicht immer aufsteigend.
# Werte empirisch (ffprobe, int.Doku: H264+Bitrate_Tabelle, Basis 25 fps)
#	
def mvw_get_res(url):
	PLog('mvw_get_res: ' + url) 
	br=0

	# weitere ARD-Folgen: _C _E _X, _L _N _P (nicht berücksichtigt)
	if ".l." in url or ".ml." in url	or "xx.l." in url:	# ard Folge: .l. .ml. .xxl.
		marks=[".l.|960x540|SD", ".ml.|640x360|SD", ".xxl.|1920x1080|HD"]
		for item in marks:
			urlmark, res, videomark	= item.split("|")
			if urlmark in url:
				return res, videomark

	if "_MP4-" in url:
		try:												# 1. Bitrate aus arte-Url				
			br = re.search(r'_MP4-(\d+)_', url).group(1)	#  ..08943449_MP4-2200_AMM..
			br = int(br); PLog("br: %d" % br)
		except Exception as exception:					
			PLog("br_error_arte:  " + str(exception))
			br=0			
	
	if "0k_p" in url:										# zdf ..trag_log_3360k_p36v17.mp4
		try:												# 1. Bitrate aus arte-Url				
			br = re.search(r'_(\d+)k_p', url).group(1)
			br = int(br); PLog("br: %d" % br)
		except Exception as exception:					
			PLog("br_error_zdf:  " + str(exception))
			br=0
				
	if url.endswith("kbit.mp4"):							# DasErste ..-50p-3200kbit.mp4
		try:												# 1. Bitrate aus arte-Url				
			br = re.search(r'-(\d+)kbit', url).group(1)
			br = int(br); PLog("br: %d" % br)
		except Exception as exception:					
			PLog("br_error_DasErste:  " + str(exception))
			br=0	
			
	#---------------------------------------------------	# Zuordnung br -> res
	res=""; videomark=""									# Fallback-Marke Aufrufer
	br_res_tab = ["800|640x480|SD", "1600|720x406|SD", 		# Zuordnung Bitrate | Auflösung | Videomarke
					"3400|1280x720|HD", "6700|1920x1080|Full HD"]
	if br > 0:
		PLog("check_tab_for: %d" % br)
		for item in br_res_tab:
			tab_br, res, mark = item.split("|")
			if br < int(tab_br):
				PLog("found: br %d | %s" % (br, item))
				return res, mark
	else:
		PLog("get_res_failed")
		return res, videomark

# ----------------------------------------------------------------------
# get_page in util wegen Post-Daten nicht geeignet
#
def get_mvw_page(data):
	PLog('get_mvw_page:') 
	
	path = "https://mediathekviewweb.de/api/query"
	header = {"user-agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/98.0.4758.80 Safari/537.36", \
		"content-type": "text/plain;charset=UTF-8", "accept": "*/*"}
	data = data.encode('utf-8')

	msg = ''; page = ''	
	try:
		req = Request(path, data=data, headers=header)
		r = urlopen(req)
		PLog(r.info())
		page = r.read()		
		page = page.decode('utf-8')
	except Exception as e:
		page=''
		msg=str(e)
		PLog(msg)
	
	PLog(len(page))
	PLog(page[:100])
	return page,msg

# ----------------------------------------------------------------------
	
	
	
	


