"""
Пользовательские фильтры шаблонов для форматирования координат.

Этот модуль содержит фильтры Django для форматирования географических координат
в читаемый вид в шаблонах.
"""

# Standard library imports
from typing import Optional

# Django imports
from django import template
from django.contrib.gis.geos import Point

register = template.Library()


@register.filter(name='format_coords')
def format_coords(point: Optional[Point]) -> str:
    """
    Форматирует объект Point в читаемую строку координат.

    Args:
        point (Point): Объект Point из GeoDjango или None.

    Returns:
        str: Отформатированная строка координат в формате "XXN/S YYE/W"
             или "-" если point равен None.

    Example:
        В шаблоне:
        {{ geo_obj.coords|format_coords }}
        
        Результат:
        "55.75N 37.62E"
    """
    if not point:
        return "-"
    
    try:
        longitude = point.coords[0]
        latitude = point.coords[1]
        
        lon_direction = "E" if longitude > 0 else "W"
        lat_direction = "N" if latitude > 0 else "S"
        
        lon_value = abs(longitude)
        lat_value = abs(latitude)
        
        return f"{lat_value}{lat_direction} {lon_value}{lon_direction}"
    except (AttributeError, IndexError, TypeError):
        return "-"


@register.filter(name='format_coords_decimal')
def format_coords_decimal(point: Optional[Point], precision: int = 6) -> str:
    """
    Форматирует объект Point в десятичные координаты с заданной точностью.

    Args:
        point (Point): Объект Point из GeoDjango или None.
        precision (int): Количество знаков после запятой (по умолчанию 6).

    Returns:
        str: Отформатированная строка координат в формате "lat, lon"
             или "-" если point равен None.

    Example:
        В шаблоне:
        {{ geo_obj.coords|format_coords_decimal:4 }}
        
        Результат:
        "55.7500, 37.6200"
    """
    if not point:
        return "-"
    
    try:
        longitude = point.coords[0]
        latitude = point.coords[1]
        
        format_str = f"{{:.{precision}f}}, {{:.{precision}f}}"
        return format_str.format(latitude, longitude)
    except (AttributeError, IndexError, TypeError, ValueError):
        return "-"


@register.filter(name='coords_to_lat')
def coords_to_lat(point: Optional[Point]) -> Optional[float]:
    """
    Извлекает широту из объекта Point.

    Args:
        point (Point): Объект Point из GeoDjango или None.

    Returns:
        float: Значение широты или None если point равен None.

    Example:
        В шаблоне:
        {{ geo_obj.coords|coords_to_lat }}
    """
    if not point:
        return None
    
    try:
        return point.coords[1]
    except (AttributeError, IndexError, TypeError):
        return None


@register.filter(name='coords_to_lon')
def coords_to_lon(point: Optional[Point]) -> Optional[float]:
    """
    Извлекает долготу из объекта Point.

    Args:
        point (Point): Объект Point из GeoDjango или None.

    Returns:
        float: Значение долготы или None если point равен None.

    Example:
        В шаблоне:
        {{ geo_obj.coords|coords_to_lon }}
    """
    if not point:
        return None
    
    try:
        return point.coords[0]
    except (AttributeError, IndexError, TypeError):
        return None
