from __future__ import annotations # Delays annotation evaluation, allowing modern 3.10+ type syntax and forward references in older Python versions 3.8 and 3.9
#import numpy as np
import logging
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import matplotlib.dates as mdates
from datetime import datetime, timedelta
from threading import Thread

from pipeline_eds import helpers
from pipeline_eds.plotbuffer import PlotBuffer  # Adjust import path as needed
from pipeline_eds.time_manager import TimeManager
from pipeline_eds.plottools import linspace_indices



logger = logging.getLogger(__name__)

PADDING_RATIO = 0.25

def run_gui(buffer: PlotBuffer, update_interval_ms=1000):
    """
    Runs a matplotlib live updating plot based on the PlotBuffer content.
    `update_interval_ms` controls how often the plot refreshes (default 1000ms = 1s).
    """
    # plt.style.use('seaborn-darkgrid')
    plt.style.use('ggplot')  # matplotlib built-in style as a lightweight alternative

    fig, ax = plt.subplots(figsize=(10, 6))
    ax.set_title("Live Pipeline Data")
    ax.set_xlabel("Time")
    ax.set_ylabel("Value")
    # Auto-locate ticks and auto-format dates
    locator = mdates.AutoDateLocator()
    formatter = mdates.AutoDateFormatter(locator)
    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(formatter)

    lines = {}
    legend_labels = []

    def init():
        ax.clear()
        ax.set_title("Live Pipeline Data")
        ax.set_xlabel("Time")
        ax.set_ylabel("Value")
        return []

    def update(frame):
        data = buffer.get_all()
        if not data:
            return []

        # Add/update lines for each series
        for label, series in data.items():
            x_vals = series["x"]
            y_vals = series["y"]
            # Decide how many ticks you want (e.g., max 6)
            num_ticks = min(6, len(x_vals))

            # Choose evenly spaced indices
            #indices = np.linspace(0, len(x_vals) - 1, num_ticks, dtype=int)
            indices = linspace_indices(start=0, stop = len(x_vals) - 1, num=num_ticks, length=len(x_vals))
            
            if label not in lines:
                # Create new line
                line, = ax.plot(x_vals, y_vals, label=label)
                lines[label] = line
                legend_labels.append(label)
                ax.legend()
            else:
                lines[label].set_data(x_vals, y_vals)

        # Format x-axis ticks as human readable time strings

        # Tick positions are x values at those indices
        tick_positions = [x_vals[i] for i in indices]
        tick_labels = [TimeManager(ts).as_formatted_time() for ts in tick_positions]
        # Convert UNIX timestamps to formatted strings on x-axis
        #xticks = ax.get_xticks()
        #xtick_labels = [TimeManager(x).as_formatted_time() for x in xticks]
        ax.set_xticks(tick_positions)
        #ax.set_xticklabels(xtick_labels, rotation=45, ha='right')
        ax.set_xticklabels(tick_labels, rotation=45, ha='right')

        return list(lines.values())

    ani = animation.FuncAnimation(
        fig,
        update,
        init_func=init,
        interval=update_interval_ms,
        blit=False  # blit=True can be tricky with multiple lines and dynamic axes
    )

    plt.tight_layout()
    plt.show()

def show_static(buffer: PlotBuffer):
    """
    Show a static matplotlib plot of the current PlotBuffer contents,
    with automatic date formatting based on time span.
    """
    plt.style.use('ggplot')
    fig, ax = plt.subplots(figsize=(10, 6))
    ax.set_title("EDS Trend")
    ax.set_xlabel("Time")
    ax.set_ylabel("Value")

    data = buffer.get_all()
    if not data:
        ax.text(0.5, 0.5, "No data to display", ha='center', va='center')
        plt.show()
        return

    for label, series in data.items():
        # Convert strings to datetime objects for better handling
        x_vals = [TimeManager(ts).as_datetime() for ts in series["x"]]
        y_vals = series["y"]

        ax.plot(x_vals, y_vals, marker='o', linestyle='-', label=label)

    # Let matplotlib auto-locate ticks and auto-format
    locator = mdates.AutoDateLocator()
    formatter = mdates.AutoDateFormatter(locator)
    ax.xaxis.set_major_locator(locator)
    ax.xaxis.set_major_formatter(formatter)

    plt.setp(ax.get_xticklabels(), rotation=45, ha='right')
    ax.legend()
    plt.tight_layout()
    plt.show()
    return fig
