from PyQt5.QtCore import Qt, QRect, QPropertyAnimation, pyqtProperty, pyqtSignal, QPoint
from PyQt5.QtGui import QPainter, QColor
from PyQt5.QtWidgets import QWidget

class ToggleSwitch(QWidget):
    clicked = pyqtSignal(bool)

    def __init__(self, parent=None):
        super(ToggleSwitch, self).__init__(parent)
        self.setFixedSize(40, 20)
        self._checked = False
        self._circle_color_checked = QColor('red')
        self._circle_color_unchecked = QColor('gray')
        self._background_color = QColor('white')
        self._circle_pos = QPoint(0, 0)  # Circle's initial position.
        self.animation = QPropertyAnimation(self, b"circle_pos")
        self.animation.setDuration(250)

        self._init_position()

    @pyqtProperty(QPoint)
    def circle_pos(self):
        return self._circle_pos

    @circle_pos.setter
    def circle_pos(self, pos):
        self._circle_pos = pos
        self.update()

    def _init_position(self):
        if self._checked:
            self._circle_pos.setX(10)
        else:
            self._circle_pos.setX(0)

    def mousePressEvent(self, event):
        if event.button() == Qt.LeftButton:
            self._checked = not self._checked
            self.clicked.emit(self._checked)
            self._update_animation()
            self.update()
        super(ToggleSwitch, self).mousePressEvent(event)

    def _update_animation(self):
        if self._checked:
            self.animation.setStartValue(QPoint(0, 0))
            self.animation.setEndValue(QPoint(20, 0))
        else:
            self.animation.setStartValue(QPoint(20, 0))
            self.animation.setEndValue(QPoint(0, 0))
        self.animation.start()

    def paintEvent(self, event):
        painter = QPainter(self)
        painter.setRenderHint(QPainter.Antialiasing)
        painter.setPen(Qt.NoPen)
        painter.setBrush(self._background_color)
        painter.drawRoundedRect(QRect(0, 0, 40, 20), 10, 10)

        circle_color = self._circle_color_checked if self._checked else self._circle_color_unchecked

        painter.setBrush(circle_color)
        painter.drawEllipse(self._circle_pos.x(), self._circle_pos.y(), 20, 20)

    def setChecked(self, checked):
        if self._checked != checked:
            self._checked = checked
            self._update_animation()
            self.update()
            
    def isChecked(self):
        return self._checked
    
    def setState(self, state):
        """ToggleSwitch의 상태를 설정합니다.

        Args:
            state (bool): True로 설정하면 스위치를 체크 상태로, False로 설정하면 언체크 상태로 변경합니다.
        """
        if self._checked != state:
            self._checked = state
            self._update_animation()
            self.clicked.emit(self._checked)
            self.update()