# -*- coding: utf-8 -*-

import sys
import os
import re
import xbmc
import xbmcgui
import xbmcplugin
import xbmcaddon
import json
import xbmcvfs
import shutil
import uuid
import base64
import hashlib
import random
import string
import gzip
import html
import time
from datetime import datetime, timedelta
from calendar import timegm as TGM
import concurrent.futures
import inputstreamhelper
from urllib.parse import urlparse, parse_qs, parse_qsl, quote, urlencode
from urllib.request import urlopen, Request, build_opener, HTTPCookieProcessor
from urllib.error import HTTPError
from http.cookiejar import CookieJar


addon_tvnow = xbmcaddon.Addon()
addon_id = addon_tvnow.getAddonInfo('id')
addon_name = addon_tvnow.getAddonInfo('name')
addon_version = addon_tvnow.getAddonInfo('version')
addon_path = xbmcvfs.translatePath(addon_tvnow.getAddonInfo('path'))
data_path = xbmcvfs.translatePath(addon_tvnow.getAddonInfo('profile'))
dialog = xbmcgui.Dialog()
icon = os.path.join(addon_path, 'resources', 'media', 'icon.png')
defaultFanart = os.path.join(addon_path, 'resources', 'media', 'fanart.jpg')
artpic = os.path.join(addon_path, 'resources', 'media', '')
FAVORIT_FILE = xbmcvfs.translatePath(os.path.join(data_path, 'favorites_data.gz'))
SHOWS_FILE = xbmcvfs.translatePath(os.path.join(data_path, 'shows_data.gz'))
SERIES_FILE = xbmcvfs.translatePath(os.path.join(data_path, 'series_data.gz'))
MOVIES_FILE = xbmcvfs.translatePath(os.path.join(data_path, 'movies_data.gz'))
RECOM_FILE = xbmcvfs.translatePath(os.path.join(data_path, 'recommend.gz'))
DEB_LEVEL = (xbmc.LOGINFO if addon_tvnow.getSetting('enable_debug') == 'true' else xbmc.LOGDEBUG)
KODI_ov20 = int(xbmc.getInfoLabel('System.BuildVersion')[0:2]) >= 20
KODI_un21 = int(xbmc.getInfoLabel('System.BuildVersion')[0:2]) <= 20
USERAGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:141.0) Gecko/20100101 Firefox/141.0'
ADDON_HANDLE = int(sys.argv[1])

def translation(ident):
	return addon_tvnow.getLocalizedString(ident)

def failing(content):
	log(content, xbmc.LOGERROR)

def debug_MS(content):
	log(content, DEB_LEVEL)

def log(msg, level=xbmc.LOGINFO):
	return xbmc.log(f"[{addon_id} v.{addon_version}]{str(msg)}", level)

def build_mass(body):
	return f"{sys.argv[0]}?{urlencode(body)}"

def plugin_operate(MARKING):
	check_uno = xbmc.executeJSONRPC(f'{{"jsonrpc":"2.0","id":1,"method":"Addons.GetAddonDetails","params":{{"addonid":"{MARKING}","properties":["enabled"]}}}}')
	answer_uno, answer_due = json.loads(check_uno), json.loads(f'{{"error": "{MARKING} NOT FOUND"}}')
	if not "error" in answer_uno.keys() and answer_uno.get('result', '') and answer_uno['result'].get('addon', {}).get('enabled', False) is False:
		try:
			xbmc.executeJSONRPC(f'{{"jsonrpc":"2.0","id":1,"method":"Addons.SetAddonEnabled","params":{{"addonid":"{MARKING}","enabled":true}}}}')
			failing(f"(common.plugin_operate) ERROR - ACTIVATED - ERROR :\n##### Das benötigte Addon : *{MARKING}* ist NICHT aktiviert !!! #####\n##### Es wird jetzt versucht die Aktivierung durchzuführen !!! #####")
		except: pass
		del answer_due
		check_due = xbmc.executeJSONRPC(f'{{"jsonrpc":"2.0","id":1,"method":"Addons.GetAddonDetails","params":{{"addonid":"{MARKING}","properties":["enabled"]}}}}')
		answer_due = json.loads(check_due)
	if (answer_uno.get('result', '') and answer_uno['result'].get('addon', {}).get('enabled', False) is True) or (answer_due.get('result', '') and answer_due['result'].get('addon', {}).get('enabled', False) is True):
		return True
	if answer_due.get('result', '') and answer_due['result'].get('addon', {}).get('enabled', False) is False:
		dialog.ok(addon_id, translation(30501).format(MARKING))
		failing(f"(common.plugin_operate) ERROR - ACTIVATED - ERROR :\n##### Das benötigte Addon : *{MARKING}* ist NICHT aktiviert !!! #####\n##### Eine automatische Aktivierung ist leider NICHT möglich !!! #####")
	if "error" in answer_uno.keys() or "error" in answer_due.keys():
		dialog.ok(addon_id, translation(30502).format(MARKING))
		failing(f"(common.plugin_operate) ERROR - INSTALLED - ERROR :\n##### Das benötigte Addon : *{MARKING}* ist NICHT installiert !!! #####")
	return False

def get_CentralTime(indicator, actual=True):
	CONVERTED = datetime(*(time.strptime(indicator[:19], '%Y-%m-%dT%H:%M:%S')[0:6]))
	if actual is True: LOCAL_DATE = CONVERTED
	else:
		try: # 1702235640 or 2025-02-04T18:05:00.000Z
			LOCAL_DATE = datetime.fromtimestamp(TGM(CONVERTED.timetuple()))
			assert CONVERTED.resolution >= timedelta(microseconds=1)
			LOCAL_DATE = LOCAL_DATE.replace(microsecond=CONVERTED.microsecond)
		except (ValueError, OverflowError): # ERROR on Android 32bit Systems = cannot convert unix timestamp over year 2038
			LOCAL_DATE = datetime.fromtimestamp(0) + timedelta(seconds=TGM(CONVERTED.timetuple()))
			LOCAL_DATE = LOCAL_DATE - timedelta(hours=datetime.timetuple(LOCAL_DATE).tm_isdst)
	return LOCAL_DATE

def get_Picture(elem_cat, resources, elem_url):
	if elem_cat == 'plainLandscape' and elem_url == 'absoluteUri' and resources and resources.get(elem_cat, '') and resources[elem_cat].get(elem_url, None) is not None and len(resources[elem_cat][elem_url]) > 5:
		return resources[elem_cat][elem_url]
	if elem_cat == 'artworkLandscape' and elem_url == 'absoluteUri' and resources and resources.get(elem_cat, '') and resources[elem_cat].get(elem_url, None) is not None and len(resources[elem_cat][elem_url]) > 5:
		return resources[elem_cat][elem_url]
	if elem_cat == 'artworkLandscape' and elem_url == 'url' and resources and resources.get(elem_cat, '') and resources[elem_cat].get(elem_url, None) is not None and len(resources[elem_cat][elem_url]) > 5:
		return resources[elem_cat][elem_url]
	if elem_cat == 'default' and elem_url == 'absoluteUri' and resources and resources.get(elem_cat, '') and resources[elem_cat].get(elem_url, None) is not None and len(resources[elem_cat][elem_url]) > 5:
		return resources[elem_cat][elem_url]
	if elem_cat == 'plainPortrait' and elem_url== 'absoluteUri' and resources and resources.get(elem_cat, '') and resources[elem_cat].get(elem_url, None) is not None and len(resources[elem_cat][elem_url]) > 5:
		return resources[elem_cat][elem_url]
	if elem_cat == 'artworkPortrait' and elem_url== 'absoluteUri' and resources and resources.get(elem_cat, '') and resources[elem_cat].get(elem_url, None) is not None and len(resources[elem_cat][elem_url]) > 5:
		return resources[elem_cat][elem_url]
	if elem_cat == 'artworkPortrait' and elem_url== 'url' and resources and resources.get(elem_cat, '') and resources[elem_cat].get(elem_url, None) is not None and len(resources[elem_cat][elem_url]) > 5:
		return resources[elem_cat][elem_url]
	return None

def preserve(store, timing, facts=None, arrive=None): # timing = 12 Hours storing of SHOWS_FILE+SERIES_FILE+MOVIES_FILE+RECOM_FILE / 1 Hour storing of FAVORIT_FILE
	if facts is not None:
		with gzip.open(store, 'wt', encoding='utf-8') as topics:
			json.dump(facts, topics, indent=2, sort_keys=True)
	else:
		if xbmcvfs.exists(store) and os.path.exists(store) and os.stat(store).st_size > 0:
			NOW_UTC, FILE_UTC = time.time(), (os.path.getmtime(store) + 60*60*int(timing))
			if NOW_UTC < FILE_UTC:
				with gzip.open(store, 'rt', encoding='utf-8') as topics:
					arrive = json.load(topics)
			else: xbmcvfs.delete(store)
		return arrive

def cleanUmlaut(wrong):
	if wrong is not None:
		for wg in (('ä', 'ae'), ('Ä', 'Ae'), ('ü', 'ue'), ('Ü', 'Ue'), ('ö', 'oe'), ('Ö', 'Oe'), ('ß', 'ss')):
			wrong = wrong.replace(*wg)
		wrong = wrong.strip()
	return wrong

def create_entries(metadata, SIGNS=True):
	listitem = xbmcgui.ListItem(metadata['Title'])
	vinfo = listitem.getVideoInfoTag() if KODI_ov20 else {}
	if KODI_ov20: vinfo.setTitle(metadata['Title'])
	else: vinfo['Title'] = metadata['Title']
	if metadata.get('TvShowTitle', ''):
		if KODI_ov20: vinfo.setTvShowTitle(metadata['TvShowTitle'])
		else: vinfo['Tvshowtitle'] = metadata['TvShowTitle']
	description = metadata['Plot'] if metadata.get('Plot') not in ['', 'None', None] else ' '
	if KODI_ov20: vinfo.setPlot(description)
	else: vinfo['Plot'] = description
	if str(metadata.get('Duration')).isdecimal():
		if KODI_ov20: vinfo.setDuration(int(metadata['Duration']))
		else: vinfo['Duration'] = metadata['Duration']
	if str(metadata.get('Season')).isdecimal():
		if KODI_ov20: vinfo.setSeason(int(metadata['Season']))
		else: vinfo['Season'] = metadata['Season']
	if str(metadata.get('Episode')).isdecimal():
		if KODI_ov20: vinfo.setEpisode(int(metadata['Episode']))
		else: vinfo['Episode'] = metadata['Episode']
	if metadata.get('Date', ''):
		if KODI_ov20: listitem.setDateTime(metadata['Date'])
		else: vinfo['Date'] = metadata['Date']
	if metadata.get('Aired', ''):
		if KODI_ov20: vinfo.setFirstAired(metadata['Aired'])
		else: vinfo['Aired'] = metadata['Aired']
	if str(metadata.get('Year')).isdecimal():
		if KODI_ov20: vinfo.setYear(int(metadata['Year']))
		else: vinfo['Year'] = metadata['Year']
	if metadata.get('Genre', ''):
		if KODI_ov20: vinfo.setGenres([metadata['Genre']])
		else: vinfo['Genre'] = metadata['Genre']
	if metadata.get('Country', ''):
		if KODI_ov20: vinfo.setCountries([metadata['Country']])
		else: vinfo['Country'] = metadata['Country']
	if metadata.get('Cast', '') and isinstance(metadata.get('Cast'), (list, tuple)):
		if KODI_ov20: vinfo.setCast(metadata['Cast'])
		else: listitem.setCast(metadata['Cast'])
	if metadata.get('Mpaa', ''):
		if KODI_ov20: vinfo.setMpaa(str(metadata['Mpaa']))
		else: vinfo['Mpaa'] = str(metadata['Mpaa'])
	if KODI_ov20: vinfo.setStudios(['rtl+'])
	else: vinfo['Studio'] = 'rtl+'
	if metadata.get('Mediatype', ''):
		if KODI_ov20: vinfo.setMediaType(metadata['Mediatype'])
		else: vinfo['Mediatype'] = metadata['Mediatype']
	picture, portrait = metadata.get('Image', icon), (metadata.get('Poster', '') or metadata.get('Image', icon))
	listitem.setArt({'icon': icon, 'thumb': picture, 'poster': portrait, 'fanart': defaultFanart})
	if picture and not artpic in picture and SIGNS is True:
		listitem.setArt({'fanart': picture})
	if metadata.get('Reference') == 'Single':
		listitem.setProperty('IsPlayable', 'true')
	if not KODI_ov20: listitem.setInfo('Video', vinfo)
	return listitem

def addDir(params, listitem, folder=True):
	uws = build_mass(params)
	listitem.setPath(uws)
	return xbmcplugin.addDirectoryItem(ADDON_HANDLE, uws, listitem, folder)
