# -*- coding: utf-8 -*-
# plugin.video.alkoflix
# resources/lib/modules/upnext_integration.py

import base64
import copy
import json
from modules import kodi_utils, settings

ADDON_ID = kodi_utils.get_addoninfo('id')
SENDER = '%s.SIGNAL' % ADDON_ID

# Vérifie si le service Up Next est installé et activé.
# Le test JSON-RPC est prioritaire, avec un fallback Kodi plus simple.
def service_available():
	try:
		payload = {
			'jsonrpc': '2.0',
			'id': 0,
			'method': 'Addons.GetAddonDetails',
			'params': {
				'addonid': 'service.upnext',
				'properties': ['enabled']
			}
		}
		result = json.loads(kodi_utils.execJSONRPC(json.dumps(payload)))
		return result.get('result', {}).get('addon', {}).get('enabled') is True
	except:
		try: return kodi_utils.get_visibility('System.HasAddon(service.upnext)')
		except: return False

# Envoie un signal JSON-RPC à service.upnext.
def _jsonrpc_notify(sender, message, data):
	try:
		payload = {
			'jsonrpc': '2.0',
			'id': 0,
			'method': 'JSONRPC.NotifyAll',
			'params': {
				'sender': sender,
				'message': message,
				'data': data
			}
		}
		result = json.loads(kodi_utils.execJSONRPC(json.dumps(payload)))
		return result.get('result') == 'OK'
	except:
		return False

# Prépare et envoie les informations attendues par Up Next.
def _upnext_signal(next_info):
	try:
		data = base64.b64encode(json.dumps(next_info).encode('utf-8')).decode('utf-8')
		return _jsonrpc_notify(SENDER, 'upnext_data', [data])
	except:
		return False

# Convertit une valeur en entier sans faire échouer la notification Up Next.
def _safe_int(value, fallback=0):
	try: return int(value)
	except: return fallback

# Identifiant interne utilisé pour éviter de relancer le même épisode.
def _episode_id(meta):
	return '%s:%s:%s' % (meta.get('tmdb_id', ''), meta.get('season', ''), meta.get('episode', ''))

# Prépare les images transmises à la fenêtre Up Next.
def _art(meta):
	poster_main, poster_backup, fanart_main, fanart_backup = settings.get_art_provider()
	poster = meta.get(poster_main) or meta.get(poster_backup) or meta.get('poster') or meta.get('tmdbposter') or ''
	fanart = meta.get(fanart_main) or meta.get(fanart_backup) or meta.get('fanart') or meta.get('tmdbfanart') or ''
	landscape = meta.get('landscape') or meta.get('landscape_tvshow') or fanart
	thumb = meta.get('thumb') or meta.get('still') or meta.get('screenshot') or landscape or fanart or poster
	return {
		'thumb': thumb,
		'tvshow.clearart': meta.get('clearart') or '',
		'tvshow.clearlogo': meta.get('clearlogo') or meta.get('tmdblogo') or '',
		'tvshow.fanart': fanart,
		'tvshow.landscape': landscape,
		'tvshow.poster': poster
	}

# Formate les données d'un épisode selon la structure attendue par Up Next.
def _episode_payload(meta):
	return {
		'episodeid': _episode_id(meta),
		'tvshowid': str(meta.get('tmdb_id') or meta.get('tvdb_id') or ''),
		'title': meta.get('ep_name') or meta.get('title') or '',
		'art': _art(meta),
		'season': _safe_int(meta.get('season')),
		'episode': _safe_int(meta.get('episode')),
		'showtitle': meta.get('title') or meta.get('tvshowtitle') or '',
		'plot': meta.get('plot') or '',
		'playcount': _safe_int(meta.get('playcount')),
		'rating': meta.get('rating') or 0,
		'firstaired': meta.get('premiered') or meta.get('aired') or meta.get('air_date') or '',
		'runtime': _safe_int(meta.get('duration'))
	}

# Prépare les paramètres de lecture que Up Next renverra à alkoFlix.
def _next_play_info(current_meta, next_meta, next_params, autoplay=True):
	params = dict(next_params)
	binge_group = ''
	try: binge_group = kodi_utils.get_property('alkoflix_binge_group') or ''
	except: binge_group = ''

	# En mode Up Next, lorsqu'un premier lien a été choisi manuellement,
	# le groupe de continuité permet de poursuivre automatiquement avec
	# un lien similaire, même si l'autoplay global des épisodes est désactivé.
	# Sans groupe mémorisé, on conserve le comportement demandé par l'appelant.
	upnext_binge_autoplay = bool(binge_group and not autoplay)
	params.update({
		'mode': 'play_media',
		'media_type': 'episode',
		'autoplay': 'true' if (autoplay or upnext_binge_autoplay) else 'false',
		'nextep_handoff': _episode_id(current_meta),
		'tmdb_id': next_meta.get('tmdb_id') or params.get('tmdb_id'),
		'season': next_meta.get('season') or params.get('season'),
		'episode': next_meta.get('episode') or params.get('episode'),
		'tvshowtitle': next_meta.get('rootname') or next_meta.get('title') or params.get('tvshowtitle', '')
	})
	if binge_group: params['bingeGroup'] = binge_group
	if upnext_binge_autoplay: params['upnext_binge_autoplay'] = 'true'
	if next_meta.get('custom_title'): params['custom_title'] = next_meta.get('custom_title')
	if next_meta.get('custom_year'): params['custom_year'] = next_meta.get('custom_year')
	return params

# Point d'entrée appelé par le lecteur lorsqu'un prochain épisode est prêt.
def send(meta, notification_time, autoplay=True):
	if not service_available(): return 'unavailable'
	try:
		current_meta = copy.deepcopy(meta)
		from modules.episode_tools import nextep_playback_info
		next_meta_source = copy.deepcopy(meta)
		next_meta, next_params = nextep_playback_info(next_meta_source)
		if next_params in ('error', 'no_next_episode') or not isinstance(next_params, dict):
			return None

		next_info = {
			'current_episode': _episode_payload(current_meta),
			'next_episode': _episode_payload(next_meta),
			'play_info': _next_play_info(current_meta, next_meta, next_params, autoplay),
			'notification_time': max(_safe_int(notification_time, 30), 1)
		}
		return True if _upnext_signal(next_info) else 'unavailable'
	except:
		return None
