import FreeCADGui as Gui
import FreeCAD as App
from PySide.QtCore import QTimer
import random

def _rgb(r, g, b):
    return r/255.0, g/255.0, b/255.0, 0.0

_colors = [
    _rgb(94, 224, 174),
    _rgb(223, 234, 70),
    _rgb(35, 120, 200),
    _rgb(188, 80, 33),
    _rgb(26, 242, 69),
    _rgb(13, 41, 107),
    _rgb(153, 9, 52),
    _rgb(211, 119, 0),
    _rgb(34, 130, 7),
    _rgb(221, 79, 249)
]

class AHB_Context:
    _activeStageId: int = None
    _allStagesVisible: bool = True
    _animationActive: bool = False
    _timeSinceLastStageUpdate: int = 0

    def setActiveStage(self, stageId):
        self._activeStageId = stageId
        self._updateVisibility()

    def getActiveStage(self):
        return self._activeStageId

    def getAllStages(self):
        allStages = set()

        doc = App.ActiveDocument
        for obj in doc.Objects:
            if obj.TypeId == 'Part::Feature':
                if 'AssemblyHandbook_Stage' in obj.PropertiesList:
                    allStages.add(obj.AssemblyHandbook_Stage)

        allStages = list(allStages)
        allStages.sort()
        return allStages

    def onPartStageChanged(self, part: App.DocumentObject):
        allStages = self.getAllStages()

        doc = App.ActiveDocument

        if not 'AssemblyHandbook_Stage' in part.PropertiesList:
            part.ViewObject.ShapeColor = (0.8,0.8,0.8,0.0)

        for obj in doc.Objects:
            if obj.TypeId == 'Part::Feature':
                if 'AssemblyHandbook_Stage' in obj.PropertiesList:
                    stageIndex = allStages.index(obj.AssemblyHandbook_Stage)
                    obj.ViewObject.ShapeColor = _colors[stageIndex % len(_colors)]

        self._updateVisibility()

    def setAllStagesVisible(self, allStagesVisible):
        self._allStagesVisible = allStagesVisible
        self._updateVisibility()

    def getAllStagesVisible(self):
        return self._allStagesVisible

    def _updateVisibility(self):
        activeStageId = self.getActiveStage()

        doc = App.ActiveDocument
        for obj in doc.Objects:
            if obj.TypeId == 'Part::Feature':
                if 'AssemblyHandbook_Stage' in obj.PropertiesList:
                    obj.ViewObject.Visibility = self._allStagesVisible or activeStageId is None or obj.AssemblyHandbook_Stage <= activeStageId

    def setAnimationActive(self, animationActive):
        if self._animationActive == animationActive: return
        self._animationActive = animationActive
        self._updateAnimation()

    def getAnimationActive(self):
        return self._animationActive

    def _updateAnimation(self):
        if not self._animationActive: return

        allStages = self.getAllStages()
        if len(allStages) > 1 and self._timeSinceLastStageUpdate >= 1000:
            self._timeSinceLastStageUpdate = 0
            activeStageId = self.getActiveStage() or 0
            stageIndex = allStages.index(activeStageId) if activeStageId in allStages else 0
            stageIndex = (stageIndex + 1) % len(allStages)
            self.setActiveStage(allStages[stageIndex])

        tickResolution = 33

        import math
        from pivy import coin
        cam = Gui.ActiveDocument.ActiveView.getCameraNode()
        """rot = coin.SbRotation()
        rot.setValue(coin.SbVec3f(0, 0, 1), math.pi * tickResolution / 1000.0)
        nrot = cam.orientation.getValue() * rot
        cam.orientation = nrot"""

        center = coin.SbVec3f(1000,0,750)
        v = cam.position.getValue() - center
        v[2] = 0
        dist = v.length()
        height = cam.position.getValue()[2]
        angle = math.atan2(v[1], v[0])
        angle = angle + 0.3 * tickResolution / 1000.0
        cam.position = coin.SbVec3f(center[0] + math.cos(angle)*dist, center[1] + math.sin(angle)*dist, height)
        cam.pointAt(center, coin.SbVec3f(0,0,1))

        self._timeSinceLastStageUpdate = self._timeSinceLastStageUpdate + tickResolution
        QTimer.singleShot(tickResolution, self._updateAnimation)