# Copyright (C) 2022 Thomas Hoppe (h0bB1T). All rights reserved.
#
# Unauthorized copying of this file via any medium is strictly prohibited.
# Proprietary and confidential.

import bpy, bpy.utils.previews

from typing import Dict, Tuple

from ..utils.dev import dbg
from ..utils.blender import is_400_or_gt


class PreviewsCollection:
    """
    Single, lazy initiated preview collection.
    """
    def __init__(self, name: str):
        dbg(f'Initialize p-collection: {name}')
        self.__name = name
        self.__collection = None # type bpy.types.ImagePreviewCollection


    def __load(self, name: str, filename: str) -> bpy.types.ImagePreview:
        if not self.__collection:
            dbg(f'Create p-collection: {self.__name}')
            self.__collection = bpy.utils.previews.new()
        if name in self.__collection:
            return self.__collection[name]
        else:
            # Starting from Blender 4.0, previews are not forced to load
            # when not directly readable like virtual files in Dropbox.
            # So we access the file shortly, so the preview is available.
            # Bad experience, as the loading stalls Blender as long as images
            # are downloaded, but there's no better way yet.
            if is_400_or_gt():
                with open(filename, 'r') as f:
                    pass
            return self.__collection.load(name, filename, 'IMAGE')


    def load(self, name: str, filename: str) -> int:
        return self.__load(name, filename).icon_id
    

    def load_with_pixels(self, name: str, filename: str) -> Tuple[int, Tuple[int, int], float]:
        p = self.__load(name, filename)
        return (p.icon_id, p.image_size, p.image_pixels_float[:])


    def remove(self, id: int):
        del self.__collection[id]


    def dispose(self):
        if self.__collection:
            dbg(f'Dispose p-collection: {self.__name}')
            bpy.utils.previews.remove(self.__collection)


class PreviewsRegistry:
    """
    Helper class to manage preview collections.
    """
    def __init__(self):
        self.__collections = {} # type: Dict[str, PreviewsCollection]


    def register(self, name: str):
        if name in self.__collections:
            return
            #raise Exception(f'Preview collection {name} already registered')
        self.__collections[name] = PreviewsCollection(name)


    def collection(self, name: str) -> PreviewsCollection:
        self.register(name)
        return self.__collections[name]


    def dispose(self):
        for v in self.__collections.values():
            v.dispose()
        self.__collections.clear()


    @staticmethod
    def instance() -> 'PreviewsRegistry':
        """
        Access as singleton.
        """
        global _previews_instance
        return _previews_instance


_previews_instance = PreviewsRegistry()
