from PyQt5.QtCore import QEvent, QRectF, QSize
from PyQt5.QtSvg import QSvgWidget

from blink.resources import Resources
from blink.widgets.util import QtDynamicProperty


__all__ = ['Spinner']


class Spinner(QSvgWidget):
    icon_file = QtDynamicProperty('icon_file', type=str)
    icon_size = QtDynamicProperty('icon_size', type=QSize)
    icon_crop = QtDynamicProperty('icon_crop', type=int)

    def __init__(self, parent=None, icon='icons/spinner.svg'):
        super(Spinner, self).__init__(parent)
        self._original_viewbox = QRectF()
        self.icon_crop = 0
        self.icon_size = None
        self.icon_file = Resources.get(icon)

    def load(self, svg):
        super(Spinner, self).load(svg)
        self._original_viewbox = self.renderer().viewBoxF()
        self._update_viewbox(self.size())

    def event(self, event):
        if event.type() == QEvent.DynamicPropertyChange:
            if event.propertyName() == 'icon_crop':
                self._update_viewbox(self.size())
            elif event.propertyName() == 'icon_file':
                self.load(self.icon_file)
            elif event.propertyName() == 'icon_size':
                self.updateGeometry()
        return super(Spinner, self).event(event)

    def resizeEvent(self, event):
        super(Spinner, self).resizeEvent(event)
        self._update_viewbox(event.size())

    def sizeHint(self):
        return self.icon_size or super(Spinner, self).sizeHint()

    def _update_viewbox(self, size):
        if self._original_viewbox.isEmpty() or size.isEmpty():
            return
        if self.icon_crop >= 0:
            adjustment = self.icon_crop
        else:
            adjustment = self._original_viewbox.width() * self.icon_crop / (self._original_viewbox.width() + 2*self.icon_crop)  # (w - w * w/(w+2b))/2 = wb/(w+2b)
        viewbox = self._original_viewbox.adjusted(adjustment, adjustment, -adjustment, -adjustment)
        width = size.width()
        height = size.height()
        if height >= width:
            new_viewbox = QRectF(viewbox.x(), viewbox.y() + viewbox.height()/2 * (1 - height/width), viewbox.width(), viewbox.height() * height/width)
        else:
            new_viewbox = QRectF(viewbox.x() + viewbox.width()/2 * (1 - width/height), viewbox.y(), viewbox.width() * width/height, viewbox.height())
        self.renderer().setViewBox(new_viewbox)