# -*- coding: iso-8859-1 -*-

from .Resultable import Resultable
from .Drawable import Drawable
import numpy
import threading

#############################################################################
#                                                                           #
# Name: Class Temp_Result                                                   #
#                                                                           #
# Purpose: Specialised class of Resultable and Drawable                     #
#          Contains recorded temperature data                               #
#                                                                           #
#############################################################################

class TemperatureResult(Resultable, Drawable):
    """
    Specialised class of Resultable and Drawable
    Contains recorded temperature data.
    
    Attributes:
        x: List of timestamps in seconds.
        y: List of temperature readings in Celsius.
        setpoint: Optional list of setpoint temperatures in Celsius.
        xlabel: Label for x-axis (default: "Time (s)").
        ylabel: Label for y-axis (default: "Temperature (C)").
    """
    def __init__(self, x = None, y = None, setpoint = None, desc = None, job_id = None, job_date = None):
        Resultable.__init__(self)
        Drawable.__init__(self)
        
        # Set default labels
        self.xlabel = "Time (s)"
        self.ylabel = "Temperature (C)"
        
        # Initialize data lists
        self.x = [] if x is None else x
        self.y = [] if y is None else y
        self.setpoint = [] if setpoint is None else setpoint
        
        # Set metadata if provided
        if desc is not None:
            self.description = desc
        if job_id is not None:
            self.job_id = job_id
        if job_date is not None:
            self.job_date = job_date
        
        # Listener management for GUI updates
        self.__listeners = []
        self.__listener_lock = threading.Lock()
    
    def get_number_of_channels(self):
        """Returns 1 for temperature data."""
        return 1
    
    def register_listener(self, listener):
        """Register a listener to be notified when data changes."""
        with self.__listener_lock:
            if listener not in self.__listeners:
                self.__listeners.append(listener)
    
    def unregister_listener(self, listener):
        """Unregister a listener."""
        with self.__listener_lock:
            if listener in self.__listeners:
                self.__listeners.remove(listener)
    
    def get_xdata(self):
        """Returns the x data (timestamps) as numpy array."""
        if isinstance(self.x, numpy.ndarray):
            return self.x
        return numpy.array(self.x, dtype=float) if self.x else numpy.array([], dtype=float)
    
    def get_ydata(self, channel=0):
        """Returns the y data (temperature readings) as numpy array."""
        if channel == 0:
            if isinstance(self.y, numpy.ndarray):
                return self.y
            return numpy.array(self.y, dtype=float) if self.y else numpy.array([], dtype=float)
        return numpy.array([], dtype=float)
    
    def __len__(self):
        """Returns the number of data points."""
        return len(self.y) if self.y else 0
    
    def uses_statistics(self):
        """Returns False as temperature data doesn't use statistics."""
        return False
    
    def ready_for_drawing_error(self):
        """Returns False as temperature data doesn't have error bars."""
        return False
    
    def get_yerr(self, channel=0):
        """Returns empty error data."""
        return numpy.array([], dtype=float)
    
    def get_errorplotdata(self):
        """Returns empty error plot data."""
        return [[], [], []]
    
    def get_lineplotdata(self):
        """Returns line plot data (not used for temperature)."""
        return [[], []]
    
    def get_xmin(self):
        """Returns minimum of x."""
        xdata = self.get_xdata()
        return xdata.min() if len(xdata) > 0 else 0
    
    def get_xmax(self):
        """Returns maximum of x."""
        xdata = self.get_xdata()
        return xdata.max() if len(xdata) > 0 else 0
    
    def get_ymin(self):
        """Returns minimum of y."""
        ydata = self.get_ydata(0)
        return ydata.min() if len(ydata) > 0 else 0
    
    def get_ymax(self):
        """Returns maximum of y."""
        ydata = self.get_ydata(0)
        return ydata.max() if len(ydata) > 0 else 0
    
    def get_xminpos(self):
        """Returns smallest positive value of x."""
        xdata = self.get_xdata()
        mask = xdata > 0
        if numpy.any(mask):
            return xdata[mask].min()
        return 0
    
    def get_yminpos(self):
        """Returns smallest positive value of y."""
        ydata = self.get_ydata(0)
        mask = ydata > 0
        if numpy.any(mask):
            return ydata[mask].min()
        return 0
    
    def __repr__(self):
        """String representation of the temperature result."""
        return f"TemperatureResult(points={len(self)}, job_id={self.job_id})"
