#!/usr/bin/env python
# -*- coding: utf-8 -*-
"""
resources/resolvers/dispatcher.py
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dispatcher centrale per i resolver siti.

Mappa mode_id → funzione resolver.
Il router di main.py chiama SOLO:

    from resources.resolvers.dispatcher import dispatch
    dispatch(mode_id, url, title, icon)

Per aggiungere un nuovo sito basta:
  1. Creare resources/resolvers/nomesito.py con le funzioni pubbliche
  2. Aggiungere le voci nella REGISTRY sotto
  3. Aggiungere le voci nell'XML hometor.xml con:
       <link>plugin://plugin.video.torproxy/?mode=resolver&link=URL&title2=MODE_ID</link>
       oppure <type>plugin</type> per link diretti

REGISTRY format:
  'mode_id': (module_path, function_name)

mode_id è il valore di title2 passato dal router.
"""

import sys
import os
import importlib

# Assicura che il root addon sia nel path
_ADDON_ROOT = os.path.dirname(os.path.dirname(os.path.dirname(os.path.abspath(__file__))))
if _ADDON_ROOT not in sys.path:
    sys.path.insert(0, _ADDON_ROOT)

import functions as func
import variables as var

# ──────────────────────────────────────────────────────────────────────
# REGISTRY — mappa mode_id → (modulo, funzione)
#
# Per aggiungere un nuovo sito: aggiungi righe qui e crea il file .py
# ──────────────────────────────────────────────────────────────────────

REGISTRY = {
    # ── DaddyHD ────────────────────────────────────────────────────
    # Modi esposti dal nostro menu
    'daddy_menu'           : ('resources.resolvers.daddyhd', 'show_menu'),
    'daddy_channels'       : ('resources.resolvers.daddyhd', 'show_channels'),
    'daddy_categories'     : ('resources.resolvers.daddyhd', 'show_categories'),
    'daddy_matches'        : ('resources.resolvers.daddyhd', 'show_matches'),
    'daddy_favourites'     : ('resources.resolvers.daddyhd', 'show_favourites'),
    'daddy_add_fav'        : ('resources.resolvers.daddyhd', 'add_favourite'),
    'daddy_remove_fav'     : ('resources.resolvers.daddyhd', 'remove_favourite'),
    'daddy_search'         : ('resources.resolvers.daddyhd', 'show_search'),
    'daddy_search_events'  : ('resources.resolvers.daddyhd', 'show_search_events'),
    'daddy_search_channels': ('resources.resolvers.daddyhd', 'show_search_channels'),
    'daddy_lang'           : ('resources.resolvers.daddyhd', 'show_lang'),
    'daddy_play'           : ('resources.resolvers.daddyhd', 'play'),
    'daddy_refresh'        : ('resources.resolvers.daddyhd', 'refresh'),
    'daddy_diagnostics'    : ('resources.resolvers.daddyhd', 'run_diag'),
    # Modi generati internamente da addon.py (build_url) — RICHIEDONO _params()
    'lang_channels'        : ('resources.resolvers.daddyhd', 'show_lang_channels'),
    'showChannels'         : ('resources.resolvers.daddyhd', 'show_cat_channels'),
    'trList'               : ('resources.resolvers.daddyhd', 'show_trans_list'),
    'trLinks'              : ('resources.resolvers.daddyhd', 'show_tr_links'),
    'play'                 : ('resources.resolvers.daddyhd', 'play_stream_by_params'),
    'toggle_fav'           : ('resources.resolvers.daddyhd', 'toggle_fav'),
    'extra_channels'       : ('resources.resolvers.daddyhd', 'show_extra_channels'),
    'extra_list'           : ('resources.resolvers.daddyhd', 'show_extra_list'),
    'extra_play'           : ('resources.resolvers.daddyhd', 'play_extra'),

    # ── IlCorsaroNero ──────────────────────────────────────────────
    'icn_latest' : ('resources.resolvers.ilcorsaronero', 'show_latest'),
    'icn_search' : ('resources.resolvers.ilcorsaronero', 'show_search'),
    'icn_cats'   : ('resources.resolvers.ilcorsaronero', 'show_cats'),
    'icn_cat'    : ('resources.resolvers.ilcorsaronero', 'show_cat'),

    # ── The Pirate Bay ─────────────────────────────────────────────
    'tpb_search' : ('resources.resolvers.thepiratebay', 'show_search'),
    'tpb_top'    : ('resources.resolvers.thepiratebay', 'show_top'),
    'tpb_latest' : ('resources.resolvers.thepiratebay', 'show_latest'),
    'tpb_cats'   : ('resources.resolvers.thepiratebay', 'show_cats'),
    'tpb_cat'    : ('resources.resolvers.thepiratebay', 'show_cat'),

    # ── Torch Search ───────────────────────────────────────────────
    'torch_search': ('resources.resolvers.torch_search', 'show_search'),

    # ── Zeno.FM Radio ──────────────────────────────────────────────
    'zeno_home'     : ('resources.resolvers.zeno_fm', 'show_home'),
    'zeno_genres'   : ('resources.resolvers.zeno_fm', 'show_genres'),
    'zeno_countries': ('resources.resolvers.zeno_fm', 'show_countries'),
    'zeno_stations' : ('resources.resolvers.zeno_fm', 'show_stations'),
    'zeno_search'   : ('resources.resolvers.zeno_fm', 'show_search'),
    'zeno_play'     : ('resources.resolvers.zeno_fm', 'play_station'),

    # ── UKTVNow + SPFire ───────────────────────────────────────────
    # Menu root: mostra tutte le categorie di entrambi i provider
    'uktv_menu'         : ('resources.resolvers.uktvnow_sp', 'show_menu'),
    # Categorie separate (entry-point alternativi)
    'uktv_tv_cats'      : ('resources.resolvers.uktvnow_sp', 'show_tv_categories'),
    'uktv_sp_cats'      : ('resources.resolvers.uktvnow_sp', 'show_sp_categories'),
    # Lista canali per categoria  (url = cat_id)
    'uktv_tv_channels'  : ('resources.resolvers.uktvnow_sp', 'show_tv_channels'),
    'uktv_sp_channels'  : ('resources.resolvers.uktvnow_sp', 'show_sp_channels'),
    # Riproduzione     (url = pk_id)
    'uktv_play_tv'      : ('resources.resolvers.uktvnow_sp', 'play_tv'),
    'uktv_play_sp'      : ('resources.resolvers.uktvnow_sp', 'play_sp'),
    # Forza aggiornamento canali
    'uktv_update'       : ('resources.resolvers.uktvnow_sp', 'force_update'),

    # ── Aggiungi altri siti qui ────────────────────────────────────
    # 'nomesito_action': ('resources.resolvers.nomesito', 'show_action'),
}


# ──────────────────────────────────────────────────────────────────────
# DISPATCHER
# ──────────────────────────────────────────────────────────────────────

def dispatch(mode_id: str, url: str = '', title: str = '', icon: str = '') -> bool:
    """
    Chiama la funzione resolver corrispondente a mode_id.

    Parametri:
        mode_id : identificatore azione (es. 'icn_latest', 'tpb_search')
        url     : URL opzionale passato al resolver (es. URL categoria)
        title   : titolo opzionale
        icon    : icona opzionale

    Restituisce True se il dispatcher ha gestito la richiesta, False altrimenti.
    Il router di main.py usa il valore di ritorno per decidere se chiudere
    la directory.
    """
    if not mode_id:
        func.log('[resolver] dispatch: mode_id vuoto')
        return False

    entry = REGISTRY.get(mode_id)
    if not entry:
        func.log(f'[resolver] dispatch: mode_id "{mode_id}" non in REGISTRY')
        func.ok_dialog(
            f'Resolver "{mode_id}" non trovato.\n'
            'Aggiorna il file dispatcher.py per aggiungere questo sito.'
        )
        return False

    module_path, fn_name = entry
    func.log(f'[resolver] dispatch: {mode_id} → {module_path}.{fn_name}')

    try:
        module = importlib.import_module(module_path)
    except ImportError as e:
        func.log(f'[resolver] import fallito ({module_path}): {e}')
        func.ok_dialog(f'Impossibile caricare il resolver:\n{module_path}\n\nErrore: {e}')
        return False

    fn = getattr(module, fn_name, None)
    if fn is None:
        func.log(f'[resolver] funzione "{fn_name}" non trovata in {module_path}')
        func.ok_dialog(f'Funzione "{fn_name}" mancante nel resolver {module_path}')
        return False

    try:
        # Chiama con o senza argomenti secondo la firma della funzione
        import inspect
        sig = inspect.signature(fn)
        nparams = len([
            p for p in sig.parameters.values()
            if p.default is inspect.Parameter.empty
        ])

        if nparams == 0:
            fn()
        elif nparams == 1:
            fn(url)
        else:
            fn(url, title)

        return True

    except Exception as e:
        import traceback
        err = traceback.format_exc()
        func.log(f'[resolver] errore in {module_path}.{fn_name}: {err}')
        func.ok_dialog(f'Errore nel resolver {mode_id}:\n{e}')
        return False


def list_resolvers() -> list:
    """Restituisce la lista dei mode_id registrati (utile per debug)."""
    return sorted(REGISTRY.keys())
