"""
Data averaging functions for Tilt sensors.

Applies smoothing and averaging over time windows.
"""

import numpy as np
import logging
from typing import Tuple
from scipy.ndimage import gaussian_filter1d

logger = logging.getLogger(__name__)


def average_tilt_link_hr_data(
    angle_data: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average Tilt Link HR data using Gaussian smoothing.

    Converts MATLAB MediaDati_TLHR.m function.

    Args:
        angle_data: Angle data array
        timestamps: Array of timestamps
        temperature: Temperature data array
        n_points: Window size for smoothing

    Returns:
        Tuple of (smoothed_angles, timestamps, temperatures)
    """
    logger.info(f"Averaging Tilt Link HR data with window size {n_points}")

    n_timestamps = len(angle_data)

    if n_points > n_timestamps:
        logger.warning(f"Window size {n_points} > data length {n_timestamps}, using data length")
        n_points = n_timestamps

    # Apply Gaussian smoothing along time axis (axis=0)
    # Equivalent to MATLAB's smoothdata(data,'gaussian',n_points)
    sigma = n_points / 6.0  # Approximate conversion to Gaussian sigma

    angles_smoothed = np.zeros_like(angle_data)

    for i in range(angle_data.shape[1]):
        angles_smoothed[:, i] = gaussian_filter1d(angle_data[:, i], sigma=sigma, axis=0)

    # Temperature is not averaged (keep as is for filter application)
    temp_out = temperature.copy()

    logger.info(f"Applied Gaussian smoothing with sigma={sigma:.2f}")

    return angles_smoothed, timestamps, temp_out


def average_tilt_link_data(
    acceleration: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average Tilt Link data using moving average or Gaussian smoothing.

    Args:
        acceleration: Acceleration data array
        timestamps: Array of timestamps
        temperature: Temperature data array
        n_points: Window size for averaging

    Returns:
        Tuple of (averaged_acceleration, timestamps, temperatures)
    """
    logger.info(f"Averaging Tilt Link data with window size {n_points}")

    if len(acceleration) < n_points:
        logger.warning(f"Not enough data points for averaging")
        return acceleration, timestamps, temperature

    # Apply Gaussian smoothing
    sigma = n_points / 6.0
    acc_smoothed = np.zeros_like(acceleration)

    for i in range(acceleration.shape[1]):
        acc_smoothed[:, i] = gaussian_filter1d(acceleration[:, i], sigma=sigma, axis=0)

    return acc_smoothed, timestamps, temperature


def average_biaxial_link_data(
    data: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average Biaxial Link data.

    Args:
        data: Sensor data array
        timestamps: Array of timestamps
        temperature: Temperature data array
        n_points: Window size for averaging

    Returns:
        Tuple of (averaged_data, timestamps, temperatures)
    """
    logger.info(f"Averaging Biaxial Link data with window size {n_points}")

    if len(data) < n_points:
        return data, timestamps, temperature

    sigma = n_points / 6.0
    data_smoothed = np.zeros_like(data)

    for i in range(data.shape[1]):
        data_smoothed[:, i] = gaussian_filter1d(data[:, i], sigma=sigma, axis=0)

    return data_smoothed, timestamps, temperature


def average_pendulum_link_data(
    data: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average Pendulum Link data.

    Converts MATLAB MediaDati_PL.m function.

    Args:
        data: Sensor data array
        timestamps: Array of timestamps
        temperature: Temperature data array
        n_points: Window size for averaging

    Returns:
        Tuple of (averaged_data, timestamps, temperatures)
    """
    logger.info(f"Averaging Pendulum Link data with window size {n_points}")

    if len(data) < n_points:
        return data, timestamps, temperature

    sigma = n_points / 6.0
    data_smoothed = np.zeros_like(data)

    for i in range(data.shape[1]):
        data_smoothed[:, i] = gaussian_filter1d(data[:, i], sigma=sigma, axis=0)

    # Also smooth temperature for Pendulum Link
    temp_smoothed = np.zeros_like(temperature)
    for i in range(temperature.shape[1]):
        temp_smoothed[:, i] = gaussian_filter1d(temperature[:, i], sigma=sigma, axis=0)

    return data_smoothed, timestamps, temp_smoothed


def average_kessler_link_data(
    data: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average Kessler Link data.

    Converts MATLAB MediaDati_KLHR.m function.

    Args:
        data: Sensor data array
        timestamps: Array of timestamps
        temperature: Temperature data array
        n_points: Window size for averaging

    Returns:
        Tuple of (averaged_data, timestamps, temperatures)
    """
    logger.info(f"Averaging Kessler Link data with window size {n_points}")

    if len(data) < n_points:
        return data, timestamps, temperature

    sigma = n_points / 6.0
    data_smoothed = np.zeros_like(data)

    for i in range(data.shape[1]):
        data_smoothed[:, i] = gaussian_filter1d(data[:, i], sigma=sigma, axis=0)

    return data_smoothed, timestamps, temperature


def average_radial_link_data(
    data: np.ndarray,
    timestamps: np.ndarray,
    temperature: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray, np.ndarray]:
    """
    Average Radial Link data.

    Converts MATLAB MediaDati_RL.m function.

    Args:
        data: Sensor data array
        timestamps: Array of timestamps
        temperature: Temperature data array
        n_points: Window size for averaging

    Returns:
        Tuple of (averaged_data, timestamps, temperatures)
    """
    logger.info(f"Averaging Radial Link data with window size {n_points}")

    if len(data) < n_points:
        return data, timestamps, temperature

    sigma = n_points / 6.0
    data_smoothed = np.zeros_like(data)

    for i in range(data.shape[1]):
        data_smoothed[:, i] = gaussian_filter1d(data[:, i], sigma=sigma, axis=0)

    return data_smoothed, timestamps, temperature


def average_linear_link_data(
    data: np.ndarray,
    timestamps: np.ndarray,
    n_points: int
) -> Tuple[np.ndarray, np.ndarray]:
    """
    Average Linear Link data.

    Converts MATLAB MediaDati_LL.m function.

    Args:
        data: Sensor data array
        timestamps: Array of timestamps
        n_points: Window size for averaging

    Returns:
        Tuple of (averaged_data, timestamps)
    """
    logger.info(f"Averaging Linear Link data with window size {n_points}")

    if len(data) < n_points:
        return data, timestamps

    sigma = n_points / 6.0
    data_smoothed = np.zeros_like(data)

    for i in range(data.shape[1]):
        data_smoothed[:, i] = gaussian_filter1d(data[:, i], sigma=sigma, axis=0)

    return data_smoothed, timestamps


def average_temperature_data(
    temperature: np.ndarray,
    n_points: int
) -> np.ndarray:
    """
    Average temperature data using Gaussian smoothing.

    Args:
        temperature: Temperature data array
        n_points: Window size for averaging

    Returns:
        Smoothed temperature array
    """
    logger.info(f"Averaging temperature data with window size {n_points}")

    if len(temperature) < n_points:
        return temperature

    sigma = n_points / 6.0
    temp_smoothed = np.zeros_like(temperature)

    for i in range(temperature.shape[1]):
        temp_smoothed[:, i] = gaussian_filter1d(temperature[:, i], sigma=sigma, axis=0)

    return temp_smoothed
