"""Parser for extracting structured data from MAVSDK calibration progress updates."""

import re
from typing import Optional, Dict, Any, List
import math


def parse_accelerometer_progress(progress_data) -> Dict[str, Any]:
    """
    Parse accelerometer calibration progress data into structured format.
    
    Args:
        progress_data: ProgressData object from mavsdk
        
    Returns:
        Dictionary with structured calibration information
    """
    result: Dict[str, Any] = {
        "type": "accelerometer_progress",
        "progress": None,
        "status_text": None,
        "pending_orientations": [],
        "current_orientation": None,
        "current_message": None,
        "result": None,
        "is_complete": False,
    }
    
    # Extract progress if available
    if hasattr(progress_data, 'has_progress') and progress_data.has_progress:
        progress_value = progress_data.progress
        if not (math.isnan(progress_value) if isinstance(progress_value, float) else False):
            result["progress"] = float(progress_value)
    
    # Extract status text if available
    if hasattr(progress_data, 'has_status_text') and progress_data.has_status_text:
        status_text = progress_data.status_text
        result["status_text"] = status_text
        
        # Parse pending orientations (e.g., "pending: back front left right up down")
        pending_match = re.search(r'pending:\s*([a-z\s]+)', status_text, re.IGNORECASE)
        if pending_match:
            orientations = [o.strip() for o in pending_match.group(1).split() if o.strip()]
            result["pending_orientations"] = orientations
        
        # Parse current orientation being measured
        orientation_patterns = [
            r'(\w+)\s+orientation detected',
            r'(\w+)\s+side result:',
            r'(\w+)\s+side done',
            r'Hold still, measuring (\w+) side',
        ]
        for pattern in orientation_patterns:
            match = re.search(pattern, status_text, re.IGNORECASE)
            if match:
                result["current_orientation"] = match.group(1).lower()
                break
        
        # Extract result values (e.g., "down side result: [0.020 0.819 -9.750]")
        result_match = re.search(r'result:\s*\[([\d\.\-\s]+)\]', status_text)
        if result_match:
            try:
                values = [float(v) for v in result_match.group(1).split()]
                result["result"] = values
            except ValueError:
                pass
        
        # Determine current message/instruction
        if "progress" in status_text.lower() and "<" in status_text and ">" in status_text:
            # This seems to be a completion indicator (e.g., "progress <102>")
            result["is_complete"] = True
            result["current_message"] = "complete"
        elif "hold vehicle still" in status_text.lower():
            result["current_message"] = "hold_still"
        elif "detected rest position" in status_text.lower():
            result["current_message"] = "rest_detected"
        elif "measuring" in status_text.lower():
            result["current_message"] = "measuring"
        elif "done, rotate" in status_text.lower():
            result["current_message"] = "rotate"
        elif "already completed" in status_text.lower():
            result["current_message"] = "already_completed"
        elif "orientation detected" in status_text.lower():
            result["current_message"] = "orientation_detected"
        else:
            # Default: use the status text as message
            result["current_message"] = status_text
    
    return result


def parse_gyroscope_progress(progress_data) -> Dict[str, Any]:
    """
    Parse gyroscope calibration progress data into structured format.
    
    Gyroscope calibration only provides progress values (0.0 to 1.0) without status text.
    The vehicle should be kept still during calibration.
    
    Args:
        progress_data: ProgressData object from mavsdk
        
    Returns:
        Dictionary with structured calibration information
    """
    result: Dict[str, Any] = {
        "type": "gyroscope_progress",
        "progress": None,
        "status_text": None,
        "current_message": None,
        "is_complete": False,
    }
    
    if hasattr(progress_data, 'has_progress') and progress_data.has_progress:
        progress_value = progress_data.progress
        if not (math.isnan(progress_value) if isinstance(progress_value, float) else False):
            result["progress"] = float(progress_value)
            # Mark as complete when progress reaches 1.0
            if result["progress"] >= 1.0:
                result["is_complete"] = True
                result["current_message"] = "complete"
            else:
                result["current_message"] = "calibrating"
    
    if hasattr(progress_data, 'has_status_text') and progress_data.has_status_text:
        status_text = progress_data.status_text
        result["status_text"] = status_text
        if status_text and not result["current_message"]:
            result["current_message"] = status_text
    
    return result


def parse_magnetometer_progress(progress_data) -> Dict[str, Any]:
    """
    Parse magnetometer calibration progress data into structured format.
    
    Magnetometer calibration involves rotating the vehicle through different orientations
    while progress increments from 0.0 to 1.0.
    
    Args:
        progress_data: ProgressData object from mavsdk
        
    Returns:
        Dictionary with structured calibration information
    """
    result: Dict[str, Any] = {
        "type": "magnetometer_progress",
        "progress": None,
        "status_text": None,
        "pending_orientations": [],
        "current_orientation": None,
        "current_message": None,
        "is_complete": False,
    }
    
    # Extract progress if available
    if hasattr(progress_data, 'has_progress') and progress_data.has_progress:
        progress_value = progress_data.progress
        if not (math.isnan(progress_value) if isinstance(progress_value, float) else False):
            result["progress"] = float(progress_value)
            # Mark as complete when progress reaches 1.0
            if result["progress"] >= 1.0:
                result["is_complete"] = True
    
    # Extract status text if available
    if hasattr(progress_data, 'has_status_text') and progress_data.has_status_text:
        status_text = progress_data.status_text
        result["status_text"] = status_text
        
        # Parse pending orientations (e.g., "pending: back front left right up down")
        pending_match = re.search(r'pending:\s*([a-z\s]+)', status_text, re.IGNORECASE)
        if pending_match:
            orientations = [o.strip() for o in pending_match.group(1).split() if o.strip()]
            result["pending_orientations"] = orientations
        
        # Parse current orientation being measured
        orientation_patterns = [
            r'(\w+)\s+orientation detected',
            r'(\w+)\s+side done',
            r'(\w+)\s+side already completed',
        ]
        for pattern in orientation_patterns:
            match = re.search(pattern, status_text, re.IGNORECASE)
            if match:
                result["current_orientation"] = match.group(1).lower()
                break
        
        # Determine current message/instruction
        if "Rotate vehicle" in status_text:
            result["current_message"] = "rotate"
        elif "hold vehicle still" in status_text.lower():
            result["current_message"] = "hold_still"
        elif "detected rest position" in status_text.lower():
            result["current_message"] = "rest_detected"
        elif "detected motion" in status_text.lower():
            result["current_message"] = "motion_detected"
        elif "done, rotate" in status_text.lower():
            result["current_message"] = "rotate"
        elif "already completed" in status_text.lower():
            result["current_message"] = "already_completed"
        elif "orientation detected" in status_text.lower():
            result["current_message"] = "orientation_detected"
        else:
            # Default: use the status text as message
            result["current_message"] = status_text
    
    return result


def parse_horizon_progress(progress_data) -> Dict[str, Any]:
    """
    Parse level horizon calibration progress data into structured format.
    
    Horizon calibration only provides progress values (0.0 to 1.0) without status text.
    
    Args:
        progress_data: ProgressData object from mavsdk
        
    Returns:
        Dictionary with structured calibration information
    """
    result: Dict[str, Any] = {
        "type": "horizon_progress",
        "progress": None,
        "status_text": None,
        "current_message": None,
        "is_complete": False,
    }
    
    if hasattr(progress_data, 'has_progress') and progress_data.has_progress:
        progress_value = progress_data.progress
        if not (math.isnan(progress_value) if isinstance(progress_value, float) else False):
            result["progress"] = float(progress_value)
            # Mark as complete when progress reaches 1.0
            if result["progress"] >= 1.0:
                result["is_complete"] = True
                result["current_message"] = "complete"
            else:
                result["current_message"] = "calibrating"
    
    if hasattr(progress_data, 'has_status_text') and progress_data.has_status_text:
        status_text = progress_data.status_text
        result["status_text"] = status_text
        if status_text and not result["current_message"]:
            result["current_message"] = status_text
    
    return result

