#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# Fenrir TTY screen reader
# By Chrys, Storm Dragon, and contributors.

import time
from fenrirscreenreader.core.i18n import _


class command:
    def __init__(self):
        pass

    def initialize(self, environment):
        self.env = environment
        # Initialize tab completion state tracking
        if "tabCompletion" not in self.env["commandBuffer"]:
            self.env["commandBuffer"]["tabCompletion"] = {
                "lastTabTime": 0,
                "pendingCompletion": None,
                "retryCount": 0
            }

    def shutdown(self):
        pass

    def get_description(self):
        return _("Announces tab completions when detected")

    def _is_recent_tab_input(self):
        """Check if TAB was pressed recently (within 200ms window)"""
        current_time = time.time()
        tab_detected = False
        
        # Check KEY mode
        if self.env["runtime"]["InputManager"].get_shortcut_type() in ["KEY"]:
            if (self.env["runtime"]["InputManager"].get_last_deepest_input()
                in [["KEY_TAB"]]):
                tab_detected = True
                self.env["commandBuffer"]["tabCompletion"]["lastTabTime"] = current_time
        
        # Check BYTE mode
        elif self.env["runtime"]["InputManager"].get_shortcut_type() in ["BYTE"]:
            for currByte in self.env["runtime"]["ByteManager"].get_last_byte_key():
                if currByte == 9:  # Tab character
                    tab_detected = True
                    self.env["commandBuffer"]["tabCompletion"]["lastTabTime"] = current_time
        
        # Check if tab was pressed recently (200ms window)
        if not tab_detected:
            time_since_tab = current_time - self.env["commandBuffer"]["tabCompletion"]["lastTabTime"]
            if time_since_tab <= 0.2:  # 200ms window
                tab_detected = True
        
        return tab_detected

    def _is_flexible_completion_match(self, x_move, delta_text):
        """Use flexible matching instead of strict equality"""
        if not delta_text:
            return False
        
        delta_len = len(delta_text)
        
        # Exact match (preserve original behavior)
        if x_move == delta_len:
            return True
        
        # Flexible range: allow ±2 characters difference
        # Handles spacing adjustments and unicode width variations
        if abs(x_move - delta_len) <= 2 and delta_len > 0:
            return True
        
        # For longer completions, allow proportional variance
        if delta_len > 10 and abs(x_move - delta_len) <= (delta_len * 0.2):
            return True
        
        return False

    def _detect_completion_patterns(self, delta_text):
        """Detect common tab completion patterns for improved accuracy"""
        if not delta_text:
            return False
        
        delta_stripped = delta_text.strip()
        
        # File extension completion
        if '.' in delta_stripped and delta_stripped.count('.') <= 2:
            return True
        
        # Path completion (contains / or \)
        if '/' in delta_stripped or '\\' in delta_stripped:
            return True
        
        # Command parameter completion (starts with -)
        if delta_stripped.startswith('-') and len(delta_stripped) > 1:
            return True
        
        # Word boundary completion (alphanumeric content)
        if delta_stripped.isalnum() and len(delta_stripped) >= 2:
            return True
        
        return False

    def run(self):
        """Enhanced tab completion detection with improved reliability"""
        # Basic cursor movement check (preserve original logic)
        x_move = (
            self.env["screen"]["new_cursor"]["x"]
            - self.env["screen"]["old_cursor"]["x"]
        )
        if x_move <= 0:
            return

        # Enhanced tab input detection with persistence
        tab_detected = self._is_recent_tab_input()
        
        # Fallback for non-tab movements (preserve original thresholds)
        if not tab_detected:
            if x_move < 5:
                return

        # Screen delta availability check
        if not self.env["runtime"]["ScreenManager"].is_delta():
            # If tab was detected but no delta yet, store for potential retry
            if tab_detected and self.env["commandBuffer"]["tabCompletion"]["retryCount"] < 2:
                self.env["commandBuffer"]["tabCompletion"]["pendingCompletion"] = {
                    "x_move": x_move,
                    "timestamp": time.time()
                }
                self.env["commandBuffer"]["tabCompletion"]["retryCount"] += 1
            return

        delta_text = self.env["screen"]["new_delta"]
        
        # Enhanced correlation checking with flexible matching
        if not self._is_flexible_completion_match(x_move, delta_text):
            # Additional pattern-based validation for edge cases
            if not (tab_detected and self._detect_completion_patterns(delta_text)):
                return

        # Reset retry counter on successful detection
        self.env["commandBuffer"]["tabCompletion"]["retryCount"] = 0
        self.env["commandBuffer"]["tabCompletion"]["pendingCompletion"] = None

        # Mark that we've handled this delta to prevent duplicate announcements
        # This prevents the incoming text handler from also announcing the same content
        self.env["commandBuffer"]["tabCompletion"]["lastProcessedDelta"] = delta_text
        self.env["commandBuffer"]["tabCompletion"]["lastProcessedTime"] = time.time()

        # Text filtering and announcement (preserve original behavior)
        curr_delta = delta_text
        if (len(curr_delta.strip()) != len(curr_delta) and curr_delta.strip() != ""):
            curr_delta = curr_delta.strip()
        
        # Enhanced announcement with better handling of empty completions
        if curr_delta:
            self.env["runtime"]["OutputManager"].present_text(
                curr_delta, interrupt=True, announce_capital=True, flush=False
            )

    def set_callback(self, callback):
        pass
