# wcs/games/MillionaireMyTVAdapter.py
"""
Adapter between MillionaireGameController and a game window (the MyTV inline panel, the classic card, the modern card).

Maps controller callbacks to window property setProperty() calls, ensuring all UI updates go through Kodi's property
system (thread-safe), and turns what the player did (an intent, see designs.py) into controller calls. A modern design
also gets the structured properties of game_view.py after every change.
"""
import xbmc

from wcs.games import designs, game_view


ANSWER_FIRST_ID = 9500                # answer buttons A-D are 9500-9503

# Default answer button colors
COLOR_ANSWER_DEFAULT = "40FFFFFF"     # nofocus normal
COLOR_ANSWER_FOCUS = "CC2997FF"       # focus normal (blue)
COLOR_ANSWER_CORRECT = "FF34C759"     # correct (green)
COLOR_ANSWER_WRONG = "FFFF3B30"       # wrong (red)
COLOR_ANSWER_DISABLED = "15FFFFFF"    # 50:50 removed

# Ladder row colors (matching existing fullscreen dialog)
COLOR_LADDER_DEFAULT = "FF232323"
COLOR_LADDER_CURRENT = "FF335C8F"
COLOR_LADDER_COMPLETED = "FF3CB371"
COLOR_LADDER_FAILED = "FFB04A4A"
COLOR_LADDER_TEXT_DEFAULT = "AAFFFFFF"
COLOR_LADDER_TEXT_CURRENT = "FFFFFFFF"
COLOR_LADDER_TEXT_COMPLETED = "FFFFFFFF"
COLOR_LADDER_TEXT_DIM = "60FFFFFF"

# intent -> {controller state: index of the menu button the controller expects} (MillionaireGameController.handle_game_choice)
CHOICES = {
    'primary': {None: 0}, 'secondary': {None: 1},
    'start': {'millionaire_welcome': 0, 'millionaire_rules': 0, 'welcome_screen': 0},
    'rules': {'millionaire_welcome': 1},
    'back': {'millionaire_rules': 1},
    'next': {'answer_feedback': 0},
    'results': {'game_finished': 0},
    'again': {'answer_feedback': 1, 'game_over': 0, 'game_finished': 1, 'results': 0},
    'retry': {'error': 0},
}
LEAVE = ('end', 'title', 'home')       # intents that close the window (the player goes back to Home)
LOADING_LABEL = 'Načítání...'


class MillionaireMyTVAdapter:
    """Adapter between MillionaireGameController and MyTV dialog."""

    def __init__(self, dialog, series_id, title, plot, poster, fanart, logo,
                 episode_title='', season_number=None, episode_number=None,
                 media_type='series', genre='', actor_data=None, content=None, design=None, year=''):
        """
        Args:
            dialog: MyTVDialog instance (has setProperty/clearProperty)
            series_id: TMDb series ID
            title: Series name or channel name
            plot: Series/episode plot or combined plots for channel
            poster: Poster URL
            fanart: Fanart URL
            logo: Logo URL
            episode_title: Episode name (for episode mode)
            season_number: Season number (for episode mode)
            episode_number: Episode number (for episode mode)
            media_type: 'series' (default), 'channel' (mix mode), 'movie', 'actor', 'director', ...
            genre: Film/series genres (standalone modal)
            actor_data: Person data for actor/director/... games (standalone modal)
            content: content source of the game (wcs/games/content); None: the live AI chat
            design: wcs.games.designs.Design of the window; None: the classic card's controls
            year: release year of the work (modern card)
        """
        from wcs.games.MillionaireGame import MillionaireGameController

        self.dialog = dialog
        self.series_id = series_id
        self.title = title
        self.design = design or designs.CLASSIC
        self._buttons_ready = False
        self._shown = {}
        self._retired = False
        self.controller = MillionaireGameController(
            title=title, plot=plot, genre=genre, media_type=media_type,
            episode_title=episode_title,
            season_number=season_number,
            episode_number=episode_number,
            actor_data=actor_data,
            content=content
        )

        # Set UI callbacks to our adapter methods
        self.controller.set_ui_callbacks(
            update_display=self._on_display_update,
            update_buttons=self._on_buttons_update,
            update_sidebar=self._on_sidebar_update,
            show_error=self._on_error,
            set_focus=self._on_set_focus,
            start_countdown=self._on_countdown,
            close_dialog=self._on_close,
            update_millionaire_ladder=self._on_ladder_update,
            set_answer_button_colors=self._on_answer_colors
        )

        # Return-to-menu callback
        self.controller.set_return_to_menu_callback(self._on_return_to_menu)

        # Set static properties
        dialog.setProperty('WCS.Game.Poster', poster)
        dialog.setProperty('WCS.Game.Logo', logo)
        dialog.setProperty('WCS.Game.Fanart', fanart)
        dialog.setProperty('WCS.Game.SeriesName', '' if media_type == 'channel' else title)
        dialog.setProperty('WCS.Game.Name', title)
        dialog.setProperty('WCS.Game.Year', str(year or ''))
        dialog.setProperty('WCS.Game.Genre', genre or '')

        # Initialize answer colors to default
        self._reset_answer_colors()
        self._update_ladder_defaults()

    def start(self):
        """Start the game (show welcome screen)."""
        self.controller.start_specific_game()
        self._publish()

    def act(self, intent):
        """The player asked for something: an answer, a lifeline, a menu button, leaving the game."""
        controller = self.controller
        if intent.startswith('answer'):
            self.handle_answer(int(intent[6:]))
        elif intent == 'life5050':
            self.use_lifeline_5050()
        elif intent == 'lifetip':
            self.use_lifeline_tip()
        elif intent == 'lifeaudience':
            self.use_lifeline_audience()
        elif intent in LEAVE:
            self.dialog.leave(intent)
        elif intent in CHOICES:
            state = controller.game_state
            if state == 'game_finished' and getattr(controller, '_results_shown', False):
                state = 'results'
            choices = CHOICES[intent]
            index = choices.get(state, choices.get(None))
            if index is not None:
                self.handle_choice(index)

    def _publish(self):
        """Give a modern design the properties of the screen the game is on (only what changed)."""
        if self._retired or not self.design.modern:
            return
        values = game_view.view(self.controller)
        values['ButtonsReady'] = 'true' if self._buttons_ready else ''
        for key, value in values.items():
            name = 'WCS.Game.' + key
            if self._shown.get(name) != value:
                self._shown[name] = value
                self.dialog.setProperty(name, value)

    def focus_target(self):
        """The control to focus first on the screen the game is on."""
        if self.design.modern:
            return self.design.primary.get(game_view.screen_of(self.controller), self.design.menu_primary)
        return self.design.menu_primary

    def screen(self):
        return game_view.screen_of(self.controller)

    def retire(self):
        """Detach game workers before the shared shell replaces this adapter."""
        if self._retired:
            return
        self._retired = True
        controller = self.controller
        controller.set_ui_callbacks(None, None, None, None)
        controller.set_return_to_menu_callback(None)
        controller._cancel_autoplay_timer()
        controller._autoplay_enabled = False
        controller.stop_ladder_animation()
        stop_voice = getattr(controller.voice, 'stop', None)
        if stop_voice:
            stop_voice()
        from wcs.games.voice import SilentVoice
        controller.voice = SilentVoice()

    def handle_answer(self, index):
        """Handle answer button press (0-3)."""
        self.controller.answer_question(index)

    def handle_choice(self, choice_index):
        """Handle menu choice (welcome/feedback buttons)."""
        self.controller.handle_game_choice(choice_index)

    def use_lifeline_5050(self):
        """Use 50:50 lifeline."""
        self.controller.use_5050_lifeline()

    def use_lifeline_tip(self):
        """Use tip lifeline."""
        self.controller.use_tip_lifeline()

    def use_lifeline_audience(self):
        """Use audience poll lifeline."""
        self.controller.use_audience_poll_lifeline()

    @property
    def game_state(self):
        return self.controller.game_state

    def is_playing(self):
        """Return True if in active question state."""
        return self.controller.game_state in (
            'playing', 'answer_pending'
        )

    def is_answer_pending(self):
        """Return True if waiting for answer evaluation."""
        return self.controller.game_state == 'answer_pending'

    # ---- Callback handlers ----

    def _on_display_update(self, text):
        """Update title label and main content text area.

        Extracts the first non-empty line as the title (stripping Kodi
        formatting tags) and puts the remaining text into the textbox.
        """
        if self._retired:
            return
        if not text:
            self.dialog.setProperty('WCS.Game.Title', '')
            self.dialog.setProperty('WCS.Game.Text', '')
            self._publish()
            return

        lines = text.split('\n')
        # First non-empty line is the title
        title_line = lines[0] if lines else ''
        # Strip Kodi formatting tags for clean label display
        import re
        clean_title = re.sub(r'\[/?(?:COLOR|B|I|UPPERCASE)[^\]]*\]', '', title_line).strip()

        # Remaining lines (skip first line and optional empty second line)
        rest_start = 1
        if rest_start < len(lines) and lines[rest_start].strip() == '':
            rest_start = 2
        remaining = '\n'.join(lines[rest_start:])

        self.dialog.setProperty('WCS.Game.Title', clean_title)
        self.dialog.setProperty('WCS.Game.Text', remaining)
        self._publish()

    def _on_buttons_update(self, *labels):
        """Update answer button labels and show/hide footer."""
        if self._retired:
            return
        letter_map = ['A', 'B', 'C', 'D']

        # Determine if this is an answer state (show 2x2 grid) or menu state
        answer_states = ('playing', 'answer_pending')
        is_answer_state = getattr(self.controller, 'game_state', '') in answer_states

        if is_answer_state:
            # Show answer buttons (A, B, C, D grid)
            for i, label in enumerate(labels):
                if i < 4:
                    letter = letter_map[i]
                    if label:
                        self.dialog.setProperty(f'WCS.Game.Answer{letter}', f'{letter}: {label}')
                    else:
                        self.dialog.setProperty(f'WCS.Game.Answer{letter}', '')

            self._buttons_ready = False
            self.dialog.setProperty('WCS.Game.ShowAnswers', 'true')
            # Also update the question text
            question = getattr(self.controller, 'current_question', {})
            question_text = question.get('question', '') if question else ''
            self.dialog.setProperty('WCS.Game.Question', question_text)
            # Reset colors for new question
            self._reset_answer_colors()
            self._publish()
            # Focus on the first answer that is left (50:50 empties two of the buttons)
            if hasattr(self.dialog, '_delayed_focus'):
                first = next((i for i, label in enumerate(labels[:4]) if label), 0)
                self.dialog._delayed_focus(ANSWER_FIRST_ID + first, delay=0.15)
        else:
            # Menu state - map labels to menu buttons
            self.dialog.clearProperty('WCS.Game.ShowAnswers')
            # First label = MenuBtn1, second = MenuBtn2
            # Strip A:, B:, C: prefixes if present
            menu_labels = []
            for label in labels:
                if label:
                    # Remove "A: ", "B: " etc. prefix
                    if len(label) > 2 and label[1] == ':':
                        menu_labels.append(label[3:].strip())
                    else:
                        menu_labels.append(label)
            
            self.dialog.setProperty('WCS.Game.MenuBtn1', menu_labels[0] if len(menu_labels) > 0 else '')
            self.dialog.setProperty('WCS.Game.MenuBtn2', menu_labels[1] if len(menu_labels) > 1 else '')
            self._buttons_ready = bool(menu_labels) and menu_labels[0] != LOADING_LABEL
            self._publish()
            # Focus on first menu button
            if self._buttons_ready and hasattr(self.dialog, '_delayed_focus'):
                self.dialog._delayed_focus(self.focus_target(), delay=0.15)

    def _on_sidebar_update(self):
        """Update sidebar (we use ladder + lifeline state)."""
        if self._retired:
            return
        self._update_lifeline_state()
        self._publish()

    def _on_error(self, message):
        """Show error via toast."""
        if self._retired:
            return
        xbmc.log(f"[MyTV Game] Error: {message}", xbmc.LOGERROR)
        if hasattr(self.dialog, '_show_toast'):
            self.dialog._show_toast(message, 'error')

    def _on_set_focus(self, control_id):
        """Map the controller's button index to a control of the panel."""
        if self._retired:
            return
        # While a question is on, the index is the answer to focus (after 50:50 the first one that is left);
        # otherwise the first menu button.
        if self.is_playing():
            try:
                self.dialog.setFocusId(ANSWER_FIRST_ID + (control_id if control_id in range(4) else 0))
            except Exception:
                pass
        else:
            try:
                self.dialog.setFocusId(self.focus_target())
            except Exception:
                pass

    def _on_countdown(self, seconds, callback):
        """Start countdown for answer evaluation."""
        if self._retired:
            return
        self.controller.start_countdown_with_dynamic_buttons(seconds, callback)

    def _on_close(self):
        """Close game dialog."""
        if self._retired:
            return
        if hasattr(self.dialog, '_close_game_dialog'):
            self.dialog._close_game_dialog()

    def _on_return_to_menu(self):
        """Return to welcome menu."""
        if self._retired:
            return
        self.dialog.clearProperty('WCS.Game.ShowAnswers')
        self.dialog.clearProperty('WCS.Game.Question')
        self._reset_answer_colors()
        # Set menu buttons for welcome
        self.dialog.setProperty('WCS.Game.MenuBtn1', 'Hrát hru')
        self.dialog.setProperty('WCS.Game.MenuBtn2', 'Pravidla')
        try:
            self.dialog.setFocusId(9514)
        except Exception:
            pass

    def _on_ladder_update(self):
        """Update ladder from controller state."""
        if self._retired:
            return
        ladder_states = self.controller.get_millionaire_ladder_states()
        for _ctrl_id, state in ladder_states.items():
            q_num = state['question_num']
            self.dialog.setProperty(f'WCS.Game.Ladder.{q_num}', state['bgcolor'])

            # Text color
            if state['state'] == 'current':
                text_color = COLOR_LADDER_TEXT_CURRENT
            elif state['state'] == 'completed':
                text_color = COLOR_LADDER_TEXT_COMPLETED
            elif state['state'] in ('empty', 'generating'):
                text_color = COLOR_LADDER_TEXT_DEFAULT
            else:
                text_color = COLOR_LADDER_TEXT_DIM
            self.dialog.setProperty(f'WCS.Game.Ladder.{q_num}.Color', text_color)
        self._publish()

    # ---- Helper methods ----

    def _reset_answer_colors(self):
        """Reset all answer button colors to default."""
        for letter in ['A', 'B', 'C', 'D']:
            self.dialog.setProperty(f'WCS.Game.Answer{letter}.Color', COLOR_ANSWER_DEFAULT)
            self.dialog.setProperty(f'WCS.Game.Answer{letter}.FocusColor', COLOR_ANSWER_FOCUS)

    def set_answer_color(self, index, is_correct):
        """Set answer button color after evaluation."""
        letters = ['A', 'B', 'C', 'D']
        if 0 <= index < 4:
            letter = letters[index]
            color = COLOR_ANSWER_CORRECT if is_correct else COLOR_ANSWER_WRONG
            self.dialog.setProperty(f'WCS.Game.Answer{letter}.Color', color)
            self.dialog.setProperty(f'WCS.Game.Answer{letter}.FocusColor', color)

    def _on_answer_colors(self, selected_index, correct_index=None):
        """Callback pro nastavení barev odpovědí na tlačítkách.
        
        Fáze 1 (countdown): correct_index=None -> vybraná = modrá focus barva
        Fáze 2 (reveal): correct_index set -> správná = zelená, špatná = červená
        Reset: selected_index=-1 -> vše default
        """
        if self._retired:
            return
        letters = ['A', 'B', 'C', 'D']
        
        if selected_index == -1:
            # Reset všech barev
            self._reset_answer_colors()
            self._publish()
            return
        
        if correct_index is not None:
            # Fáze 2: Reveal
            for i in range(4):
                letter = letters[i]
                if i == correct_index:
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.Color', COLOR_ANSWER_CORRECT)
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.FocusColor', COLOR_ANSWER_CORRECT)
                elif i == selected_index and selected_index != correct_index:
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.Color', COLOR_ANSWER_WRONG)
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.FocusColor', COLOR_ANSWER_WRONG)
                else:
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.Color', COLOR_ANSWER_DEFAULT)
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.FocusColor', COLOR_ANSWER_FOCUS)
        else:
            # Fáze 1: Countdown - modrý highlight na vybrané
            for i in range(4):
                letter = letters[i]
                if i == selected_index:
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.Color', COLOR_ANSWER_FOCUS)
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.FocusColor', COLOR_ANSWER_FOCUS)
                else:
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.Color', COLOR_ANSWER_DEFAULT)
                    self.dialog.setProperty(f'WCS.Game.Answer{letter}.FocusColor', COLOR_ANSWER_FOCUS)
        self._publish()

    def _update_lifeline_state(self):
        """Update lifeline button states."""
        if self.controller.lifeline_5050_used:
            self.dialog.setProperty('WCS.Game.Lifeline5050', 'used')
        if self.controller.lifeline_tip_used:
            self.dialog.setProperty('WCS.Game.LifelineTip', 'used')
        if self.controller.lifeline_audience_used:
            self.dialog.setProperty('WCS.Game.LifelineAudience', 'used')

    def _update_ladder_defaults(self):
        """Set default ladder colors (all rows default state)."""
        for i in range(1, 10):
            self.dialog.setProperty(f'WCS.Game.Ladder.{i}', COLOR_LADDER_DEFAULT)
            self.dialog.setProperty(f'WCS.Game.Ladder.{i}.Color', COLOR_LADDER_TEXT_DEFAULT)

    def cleanup(self):
        """Clear all game properties."""
        props = [
            'WCS.MyTV.Game.Active', 'WCS.Game.State', 'WCS.Game.Text',
            'WCS.Game.Title',
            'WCS.Game.Question', 'WCS.Game.ShowAnswers',
            'WCS.Game.Poster', 'WCS.Game.Logo', 'WCS.Game.Fanart',
            'WCS.Game.SeriesName',
            'WCS.Game.MenuBtn1', 'WCS.Game.MenuBtn2',
            'WCS.Game.Lifeline5050', 'WCS.Game.LifelineTip',
            'WCS.Game.LifelineAudience',
        ]
        for p in props:
            self.dialog.clearProperty(p)

        for letter in ['A', 'B', 'C', 'D']:
            self.dialog.clearProperty(f'WCS.Game.Answer{letter}')
            self.dialog.clearProperty(f'WCS.Game.Answer{letter}.Color')
            self.dialog.clearProperty(f'WCS.Game.Answer{letter}.FocusColor')

        for i in range(1, 10):
            self.dialog.clearProperty(f'WCS.Game.Ladder.{i}')
            self.dialog.clearProperty(f'WCS.Game.Ladder.{i}.Color')

        for key in game_view.keys() + ['ButtonsReady', 'Name', 'Year', 'Genre']:
            self.dialog.clearProperty('WCS.Game.' + key)
        self._shown.clear()
