class ClientHangarSpace(object):
    igrCtrl = dependency.descriptor(IIGRController)
    settingsCore = dependency.descriptor(ISettingsCore)
    itemsFactory = dependency.descriptor(IGuiItemsFactory)

    def __init__(self, onVehicleLoadedCallback):
        global _HANGAR_CFGS
        self.__spaceId = None
        self.__cameraManager = None
        self.__waitCallback = None
        self.__loadingStatus = 0.0
        self.__spaceMappingId = None
        self.__onLoadedCallback = None
        self.__vEntityId = None
        self.__selectedEmblemInfo = None
        self.__showMarksOnGun = False
        self.__prevDirection = 0.0
        self.__onVehicleLoadedCallback = onVehicleLoadedCallback
        self.__gfxOptimizerMgr = None
        self.__optimizerID = None
        _HANGAR_CFGS = _readHangarSettings()
        return

    def create(self, isPremium, onSpaceLoadedCallback=None):
        global _CFG
        BigWorld.worldDrawEnabled(False)
        BigWorld.wg_setSpecialFPSMode()
        self.__onLoadedCallback = onSpaceLoadedCallback
        self.__spaceId = BigWorld.createSpace()
        isIGR = self.igrCtrl.getRoomType() == constants.IGR_TYPE.PREMIUM
        spacePath = _getHangarPath(isPremium, isIGR)
        spaceType = _getHangarType(isPremium)
        LOG_DEBUG(
            'load hangar: hangar type = <{0:>s}>, space = <{1:>s}>'.format(
                spaceType, spacePath))
        safeSpacePath = _getDefaultHangarPath(False)
        if ResMgr.openSection(spacePath) is None:
            LOG_ERROR(
                'Failed to load hangar from path: %s; default hangar will be loaded instead'
                % spacePath)
            spacePath = safeSpacePath
        try:
            self.__spaceMappingId = BigWorld.addSpaceGeometryMapping(
                self.__spaceId, None, spacePath)
        except Exception:
            try:
                LOG_CURRENT_EXCEPTION()
                spacePath = safeSpacePath
                self.__spaceMappingId = BigWorld.addSpaceGeometryMapping(
                    self.__spaceId, None, spacePath)
            except Exception:
                BigWorld.releaseSpace(self.__spaceId)
                self.__spaceMappingId = None
                self.__spaceId = None
                LOG_CURRENT_EXCEPTION()
                return

        spaceKey = _getHangarKey(spacePath)
        _CFG = copy.deepcopy(_HANGAR_CFGS[spaceKey])
        self.__vEntityId = BigWorld.createEntity(
            'HangarVehicle', self.__spaceId, 0, _CFG['v_start_pos'],
            (_CFG['v_start_angles'][2], _CFG['v_start_angles'][1],
             _CFG['v_start_angles'][0]), dict())
        self.__cameraManager = HangarCameraManager(self.__spaceId)
        self.__cameraManager.init()
        self.__waitCallback = BigWorld.callback(0.1, self.__waitLoadingSpace)
        self.__gfxOptimizerMgr = GraphicsOptimizationManager()
        size = BigWorld.screenSize()
        self.__optimizerID = self.__gfxOptimizerMgr.registerOptimizationArea(
            0, 0, size[0], size[1])
        MapActivities.g_mapActivities.generateOfflineActivities(spacePath)
        BigWorld.pauseDRRAutoscaling(True)
        return

    def recreateVehicle(self, vDesc, vState, onVehicleLoadedCallback=None):
        if not self.__vEntityId:
            return
        else:
            vehicle = BigWorld.entity(self.__vEntityId)
            if not vehicle:
                if onVehicleLoadedCallback:
                    onVehicleLoadedCallback()
                return
            if onVehicleLoadedCallback is None:
                onVehicleLoadedCallback = self.__onVehicleLoadedCallback
            vehicle.recreateVehicle(vDesc, vState, onVehicleLoadedCallback)
            return

    def removeVehicle(self):
        vehicle = BigWorld.entity(self.__vEntityId)
        if vehicle is not None:
            vehicle.removeVehicle()
        self.__selectedEmblemInfo = None
        return

    def moveVehicleTo(self, position):
        try:
            vehicle = BigWorld.entity(self.__vEntityId)
            vehicle.model.motors[0].signal = _createMatrix(
                _CFG['v_scale'], _CFG['v_start_angles'], position)
        except Exception:
            LOG_CURRENT_EXCEPTION()

    def setVehicleSelectable(self, flag):
        for entity in BigWorld.entities.values():
            from ClientSelectableCameraVehicle import ClientSelectableCameraVehicle
            if isinstance(entity, ClientSelectableCameraVehicle):
                entity.setSelectable(flag)

    def updateVehicleCustomization(self, outfit):
        vEntity = self.getVehicleEntity()
        if vEntity is not None and vEntity.isVehicleLoaded:
            outfit = outfit or self.itemsFactory.createOutfit()
            vEntity.appearance.updateCustomization(outfit)
        return

    def getCentralPointForArea(self, areaId):
        vEntity = self.getVehicleEntity()
        return vEntity.appearance.getCentralPointForArea(
            areaId
        ) if vEntity is not None and vEntity.isVehicleLoaded else None

    def destroy(self):
        self.__onLoadedCallback = None
        self.__closeOptimizedRegion()
        self.__destroy()
        return

    def spaceLoaded(self):
        return self.__loadingStatus >= 1

    def spaceLoading(self):
        return self.__waitCallback is not None

    def getSlotPositions(self):
        vEntity = self.getVehicleEntity()
        return vEntity.appearance.getSlotPositions(
        ) if vEntity is not None and vEntity.isVehicleLoaded else None

    def getVehicleEntity(self):
        return BigWorld.entity(self.__vEntityId)

    @property
    def vehicleEntityId(self):
        return self.__vEntityId

    def __destroy(self):
        LOG_DEBUG('Hangar successfully destroyed.')
        MusicControllerWWISE.unloadCustomSounds()
        if self.__cameraManager:
            self.__cameraManager.destroy()
            self.__cameraManager = None
        self.__loadingStatus = 0.0
        self.__onLoadedCallback = None
        if self.__waitCallback is not None:
            BigWorld.cancelCallback(self.__waitCallback)
            self.__waitCallback = None
        BigWorld.SetDrawInflux(False)
        MapActivities.g_mapActivities.stop()
        if self.__spaceId is not None and BigWorld.isClientSpace(
                self.__spaceId):
            if self.__spaceMappingId is not None:
                BigWorld.delSpaceGeometryMapping(self.__spaceId,
                                                 self.__spaceMappingId)
            BigWorld.clearSpace(self.__spaceId)
            BigWorld.releaseSpace(self.__spaceId)
        self.__spaceMappingId = None
        self.__spaceId = None
        self.__vEntityId = None
        BigWorld.wg_disableSpecialFPSMode()
        return

    def __waitLoadingSpace(self):
        self.__loadingStatus = BigWorld.spaceLoadStatus()
        BigWorld.worldDrawEnabled(True)
        if self.__loadingStatus < 1 or not BigWorld.virtualTextureRenderComplete(
        ):
            self.__waitCallback = BigWorld.callback(0.1,
                                                    self.__waitLoadingSpace)
        else:
            BigWorld.uniprofSceneStart()
            self.__closeOptimizedRegion()
            self.__waitCallback = None
            if self.__onLoadedCallback is not None:
                self.__onLoadedCallback()
                self.__onLoadedCallback = None
        return

    def __closeOptimizedRegion(self):
        if self.__gfxOptimizerMgr is not None:
            self.__gfxOptimizerMgr.unregisterOptimizationArea(
                self.__optimizerID)
            self.__gfxOptimizerMgr = None
            self.__optimizerID = None
        return

    def setCameraLocation(self, *args):
        self.__cameraManager.setCameraLocation(*args)

    def getCameraLocation(self):
        return self.__cameraManager.getCameraLocation()

    def locateCameraToPreview(self):
        self.__cameraManager.locateCameraToPreview()

    def locateCameraOnEmblem(self,
                             onHull,
                             emblemType,
                             emblemIdx,
                             relativeSize=0.5):
        return self.__cameraManager.locateCameraOnEmblem(
            onHull, emblemType, emblemIdx, relativeSize)

    def clearSelectedEmblemInfo(self):
        self.__cameraManager.clearSelectedEmblemInfo()

    @property
    def camera(self):
        return self.__cameraManager.camera
class ClientHangarSpace(object):
    igrCtrl = dependency.descriptor(IIGRController)
    settingsCore = dependency.descriptor(ISettingsCore)
    itemsFactory = dependency.descriptor(IGuiItemsFactory)
    mapActivities = dependency.descriptor(IMapActivities)
    turretAndGunAngles = dependency.descriptor(ITurretAndGunAngles)
    epicController = dependency.descriptor(IEpicBattleMetaGameController)

    def __init__(self, onVehicleLoadedCallback):
        global _HANGAR_CFGS
        self.__spaceId = None
        self.__cameraManager = None
        self.__waitCallback = None
        self.__loadingStatus = 0.0
        self.__spaceMappingId = None
        self.__onLoadedCallback = None
        self.__vEntityId = None
        self.__selectedEmblemInfo = None
        self.__showMarksOnGun = False
        self.__prevDirection = 0.0
        self.__onVehicleLoadedCallback = onVehicleLoadedCallback
        self.__spacePath = None
        self.__spaceVisibilityMask = None
        self.__geometryID = None
        self._vsePlans = makeMultiPlanProvider(ASPECT.HANGAR, CallableProviderType.HANGAR)
        _HANGAR_CFGS = _readHangarSettings()
        return

    def create(self, isPremium, onSpaceLoadedCallback=None):
        global _CFG
        BigWorld.worldDrawEnabled(False)
        BigWorld.wg_setSpecialFPSMode()
        self.__onLoadedCallback = onSpaceLoadedCallback
        self.__spaceId = BigWorld.createSpace(True)
        isIGR = self.igrCtrl.getRoomType() == constants.IGR_TYPE.PREMIUM
        spacePath = _getHangarPath(isPremium, isIGR)
        spaceType = _getHangarType(isPremium)
        spaceVisibilityMask = _getHangarVisibilityMask(isPremium, spacePath)
        LOG_DEBUG('load hangar: hangar type = <{0:>s}>, space = <{1:>s}>'.format(spaceType, spacePath))
        safeSpacePath = _getDefaultHangarPath(False)
        if ResMgr.openSection(spacePath) is None:
            LOG_ERROR('Failed to load hangar from path: %s; default hangar will be loaded instead' % spacePath)
            spacePath = safeSpacePath
        try:
            self.__spaceMappingId = BigWorld.addSpaceGeometryMapping(self.__spaceId, None, spacePath, spaceVisibilityMask)
        except Exception:
            try:
                LOG_CURRENT_EXCEPTION()
                spacePath = safeSpacePath
                self.__spaceMappingId = BigWorld.addSpaceGeometryMapping(self.__spaceId, None, spacePath, spaceVisibilityMask)
            except Exception:
                BigWorld.releaseSpace(self.__spaceId)
                self.__spaceMappingId = None
                self.__spaceId = None
                LOG_CURRENT_EXCEPTION()
                return

        self.__spacePath = spacePath
        self.__spaceVisibilityMask = spaceVisibilityMask
        spaceKey = _getHangarKey(spacePath)
        _CFG = copy.deepcopy(_HANGAR_CFGS[spaceKey])
        self.turretAndGunAngles.init()
        self.__vEntityId = BigWorld.createEntity('HangarVehicle', self.__spaceId, 0, _CFG['v_start_pos'], (_CFG['v_start_angles'][2], _CFG['v_start_angles'][1], _CFG['v_start_angles'][0]), dict())
        self.__cameraManager = HangarCameraManager(self.__spaceId)
        self.__cameraManager.init()
        self.__waitCallback = BigWorld.callback(0.1, self.__waitLoadingSpace)
        BigWorld.wg_enableGUIBackground(True, False)
        BigWorld.wg_setGUIBackground(_LOGIN_BLACK_BG_IMG)
        self.mapActivities.generateOfflineActivities(spacePath)
        BigWorld.pauseDRRAutoscaling(True)
        vsePlans = _CFG.get('vse_plans', None)
        if vsePlans is not None:
            self._vsePlans.load(vsePlans)
            self._vsePlans.start()
        return

    def recreateVehicle(self, vDesc, vState, onVehicleLoadedCallback=None, outfit=None):
        if not self.__vEntityId:
            return
        else:
            vehicle = BigWorld.entity(self.__vEntityId)
            if not vehicle:
                if onVehicleLoadedCallback:
                    onVehicleLoadedCallback()
                return
            if onVehicleLoadedCallback is None:
                onVehicleLoadedCallback = self.__onVehicleLoadedCallback
            vehicle.recreateVehicle(vDesc, vState, onVehicleLoadedCallback, outfit)
            return

    def removeVehicle(self):
        vehicle = BigWorld.entity(self.__vEntityId)
        if vehicle is not None:
            vehicle.removeVehicle()
        self.__selectedEmblemInfo = None
        return

    def moveVehicleTo(self, position):
        try:
            vehicle = BigWorld.entity(self.__vEntityId)
            vehicle.model.motors[0].signal = _createMatrix(1.0, _CFG['v_start_angles'], position)
        except Exception:
            LOG_CURRENT_EXCEPTION()

    def setVehicleSelectable(self, flag):
        for entity in BigWorld.entities.values():
            from ClientSelectableCameraVehicle import ClientSelectableCameraVehicle
            if isinstance(entity, ClientSelectableCameraVehicle):
                entity.setSelectable(flag)

    def updateVehicleCustomization(self, outfit):
        vEntity = self.getVehicleEntity()
        if vEntity is not None and vEntity.isVehicleLoaded:
            outfit = outfit or self.itemsFactory.createOutfit(vehicleCD=vEntity.typeDescriptor.makeCompactDescr())
            vEntity.updateVehicleCustomization(outfit)
        return

    def updateVehicleDescriptor(self, descr):
        vEntity = self.getVehicleEntity()
        if vEntity is not None and vEntity.isVehicleLoaded:
            vEntity.updateVehicleDescriptor(descr)
        return

    def getCentralPointForArea(self, areaId):
        vEntity = self.getVehicleEntity()
        return vEntity.appearance.getCentralPointForArea(areaId) if vEntity is not None and vEntity.isVehicleLoaded else None

    def destroy(self):
        self.__onLoadedCallback = None
        self.__closeOptimizedRegion()
        self.__destroy()
        return

    def spaceLoaded(self):
        return self.__loadingStatus >= 1

    def spaceLoading(self):
        return self.__waitCallback is not None

    def updateAnchorsParams(self, *args):
        vEntity = self.getVehicleEntity()
        if vEntity is not None and vEntity.appearance is not None:
            vEntity.appearance.updateAnchorsParams(*args)
        return

    def getAnchorParams(self, slotId, areaId, regionId):
        vEntity = self.getVehicleEntity()
        return vEntity.appearance.getAnchorParams(slotId, areaId, regionId) if vEntity is not None and vEntity.appearance is not None else None

    def getVehicleEntity(self):
        return BigWorld.entity(self.__vEntityId) if self.__vEntityId else None

    @property
    def vehicleEntityId(self):
        return self.__vEntityId

    def __destroy(self):
        LOG_DEBUG('Hangar successfully destroyed.')
        self._vsePlans.reset()
        MusicControllerWWISE.unloadCustomSounds()
        if self.__cameraManager:
            self.__cameraManager.destroy()
            self.__cameraManager = None
        self.__loadingStatus = 0.0
        self.__onLoadedCallback = None
        if self.__waitCallback is not None:
            BigWorld.cancelCallback(self.__waitCallback)
            self.__waitCallback = None
        BigWorld.SetDrawInflux(False)
        BigWorld.worldDrawEnabled(False)
        self.mapActivities.stop()
        if self.__spaceId is not None and BigWorld.isClientSpace(self.__spaceId):
            if self.__spaceMappingId is not None:
                BigWorld.delSpaceGeometryMapping(self.__spaceId, self.__spaceMappingId)
            BigWorld.clearSpace(self.__spaceId)
            BigWorld.releaseSpace(self.__spaceId)
        self.__spaceMappingId = None
        self.__spaceId = None
        self.__spacePath = None
        self.__spaceVisibilityMask = None
        self.__vEntityId = None
        BigWorld.wg_disableSpecialFPSMode()
        return

    def __waitLoadingSpace(self):
        self.__loadingStatus = BigWorld.spaceLoadStatus()
        BigWorld.worldDrawEnabled(True)
        if self.__loadingStatus < 1 or not BigWorld.virtualTextureRenderComplete():
            self.__waitCallback = BigWorld.callback(0.1, self.__waitLoadingSpace)
        else:
            BigWorld.uniprofSceneStart()
            self.__closeOptimizedRegion()
            self.__waitCallback = None
            if self.__onLoadedCallback is not None:
                self.__onLoadedCallback()
                self.__onLoadedCallback = None
        return

    def __closeOptimizedRegion(self):
        BigWorld.wg_enableGUIBackground(False, True)

    def getSpaceID(self):
        return self.__spaceId

    def setCameraLocation(self, *args):
        self.__cameraManager.setCameraLocation(*args)

    def getCameraLocation(self):
        return self.__cameraManager.getCameraLocation()

    def getCameraManager(self):
        return self.__cameraManager

    @property
    def camera(self):
        return self.__cameraManager.camera

    @property
    def spacePath(self):
        return self.__spacePath

    @property
    def visibilityMask(self):
        return self.__spaceVisibilityMask