import wx

# Horizontal Alignment Constants  
ESB_ALIGN_CENTER_VERTICAL = 1  
ESB_ALIGN_TOP = 2  
ESB_ALIGN_BOTTOM = 3

# Vertical Alignment Constants  
ESB_ALIGN_CENTER_HORIZONTAL = 11  
ESB_ALIGN_LEFT = 12  
ESB_ALIGN_RIGHT = 13

# Exact Fit (Either Horizontal Or Vertical Or Both) Constant  
ESB_EXACT_FIT = 20


class EnhancedStatusBarItem(object):
    def __init__(self, widget, pos, horizontalalignment=ESB_ALIGN_CENTER_HORIZONTAL, verticalalignment=ESB_ALIGN_CENTER_VERTICAL):
        self.__dict__.update(locals())


class EnhancedStatusBar(wx.StatusBar):

    def __init__(self, parent, id=wx.ID_ANY, style=wx.STB_SIZEGRIP, name="EnhancedStatusBar"):
        super().__init__(parent, id, style, name)

        self._items = {}
        self._curPos = 0  
        self._parent = parent

        self.Bind(wx.EVT_SIZE, self.OnSize)
        wx.CallAfter(self.OnSize, None)

    def OnSize(self, event):
        """Handles wx.EVT_SIZE Events For The StatusBar."""
        for pos, item in self._items.items():
            widget = item.widget  
            rect = self.GetFieldRect(pos)
            self.adjust_widget(widget, rect, item.horizontalalignment, item.verticalalignment)

        if event is not None:
            event.Skip()

    def adjust_widget(self, widget, rect, horizontalalignment, verticalalignment):
        """Adjusts widget size and position based on alignment."""
        widgetsize = widget.GetSize()

        if horizontalalignment == ESB_EXACT_FIT:
            self.fit_widget(widget, rect)
        elif horizontalalignment == ESB_ALIGN_LEFT:
            self.align_left(widget, rect, widgetsize, verticalalignment)
        elif horizontalalignment == ESB_ALIGN_RIGHT:
            self.align_right(widget, rect, widgetsize, verticalalignment)
        elif horizontalalignment == ESB_ALIGN_CENTER_HORIZONTAL:
            self.align_center_horizontal(widget, rect, widgetsize, verticalalignment)

    def fit_widget(self, widget, rect):
        widget.SetSize((rect.width - 2, rect.height - 2))
        widget.SetPosition((rect.x - 1, rect.y - 1))

    def align_left(self, widget, rect, widgetsize, verticalalignment):
        xpos = rect.x - 1  
        if verticalalignment == ESB_EXACT_FIT:
            widget.SetSize((widgetsize[0], rect.height - 2))
            widget.SetPosition((xpos, rect.y - 1))
        else:
            self.align_vertical(widget, rect, widgetsize, verticalalignment, xpos)

    def align_right(self, widget, rect, widgetsize, verticalalignment):
        xpos = rect.x + rect.width - widgetsize[0] - 1  
        if verticalalignment == ESB_EXACT_FIT:
            widget.SetSize((widgetsize[0], rect.height - 2))
            widget.SetPosition((xpos, rect.y - 1))
        else:
            self.align_vertical(widget, rect, widgetsize, verticalalignment, xpos)

    def align_vertical(self, widget, rect, widgetsize, verticalalignment, xpos):
        if verticalalignment == ESB_ALIGN_CENTER_VERTICAL:
            diffs = (rect.height - widgetsize[1]) / 2  
            widget.SetPosition((xpos, rect.y + diffs))
        elif verticalalignment == ESB_ALIGN_TOP:
            widget.SetPosition((xpos, rect.y))
        elif verticalalignment == ESB_ALIGN_BOTTOM:
            widget.SetPosition((xpos, rect.height - widgetsize[1]))

    def align_center_horizontal(self, widget, rect, widgetsize, verticalalignment):
        xpos = rect.x + (rect.width - widgetsize[0]) / 2 - 1  
        if verticalalignment == ESB_EXACT_FIT:
            widget.SetSize((widgetsize[0], rect.height))
            widget.SetPosition((xpos, rect.y))
        else:
            self.align_vertical(widget, rect, widgetsize, verticalalignment, xpos)

    def validate_alignment(self, horizontalalignment, verticalalignment):
        """Validate alignment parameters."""
        if horizontalalignment not in [ESB_ALIGN_CENTER_HORIZONTAL, ESB_EXACT_FIT, ESB_ALIGN_LEFT, ESB_ALIGN_RIGHT]:
            raise ValueError('ERROR: Parameter "horizontalalignment" Should Be One Of "ESB_ALIGN_CENTER_HORIZONTAL", "ESB_ALIGN_LEFT", "ESB_ALIGN_RIGHT", "ESB_EXACT_FIT"')

        if verticalalignment not in [ESB_ALIGN_CENTER_VERTICAL, ESB_EXACT_FIT, ESB_ALIGN_TOP, ESB_ALIGN_BOTTOM]:
            raise ValueError('ERROR: Parameter "verticalalignment" Should Be One Of "ESB_ALIGN_CENTER_VERTICAL", "ESB_ALIGN_TOP", "ESB_ALIGN_BOTTOM", "ESB_EXACT_FIT"')

    def AddWidget(self, widget, horizontalalignment=ESB_ALIGN_CENTER_HORIZONTAL, verticalalignment=ESB_ALIGN_CENTER_VERTICAL, pos=-1):
        """Add A Widget To The EnhancedStatusBar."""
        if pos == -1:
            pos = self._curPos  
            self._curPos += 1

        if self.GetFieldsCount() <= pos:
            raise ValueError("ERROR: EnhancedStatusBar has a max of %d items, you tried to set item #%d" % (self.GetFieldsCount(), pos))

        self.validate_alignment(horizontalalignment, verticalalignment)

        # Remove the existing widget if present  
        if pos in self._items:
            wx.CallAfter(self.RemoveChild, self._items[pos].widget)
            self._items[pos].widget.Destroy()

        # Add new widget
        self._items[pos] = EnhancedStatusBarItem(widget, pos, horizontalalignment, verticalalignment)
        wx.CallAfter(self.OnSize, None)

        # Set the widget size to fit within the allocated space
        rect = self.GetFieldRect(pos)
        widget.SetSize((rect.width - 2, rect.height - 2))  # Adjust size for borders

