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

import gpu

from typing import Any, Dict, List, Tuple

from ...utils.dev import log_exception
from ..previews_registry import PreviewsCollection
from .texture_info import TextureInfo
from .image_lookup import ImageLookup


class TextureEntry:
    """
    A single texture or PBR set.
    """
    def __init__(self, info: TextureInfo):
        self.info = info
        self.enum = () # type: Tuple[str, str, str, int, int ]
        self.preview_icon = None # type: str
        self.preview_icon_id = -1 
        self.icon_size = None
        self.icon_pixels = None
        self.gpu = None


    def dispose(self, thumb_cache: PreviewsCollection, image_lookup: ImageLookup):
        self.info.dispose(image_lookup)


    def create_update_preview(self, missing_only: bool, size: int, thumb_cache: PreviewsCollection):
        """
        Eventually re-render the preview.
        """
        if self.info.create_update_preview(missing_only, size):
            self.recreate_enum(thumb_cache)


    def load_preview(self, thumb_cache: PreviewsCollection, with_gpu: bool = False):
        """
        Guarantees the preview is loaded.
        """
        if self.preview_icon == None or self.preview_icon_id == -1:
            self.preview_icon = self.info.valid_preview_image() 
            self.preview_icon_id, self.icon_size, self.icon_pixels = thumb_cache.load_with_pixels(self.preview_icon, self.preview_icon)
 
        if with_gpu and not self.gpu: 
            buffer = gpu.types.Buffer('FLOAT', (1, len(self.icon_pixels)), [self.icon_pixels])
            self.gpu = gpu.types.GPUTexture(size=self.icon_size, data=buffer) 


    def recreate_enum(self, thumb_cache: PreviewsCollection):
        """
        Invalidate preview, used when preview is rerendered.
        """
        if self.preview_icon != None:
            try:
                thumb_cache.remove(self.preview_icon)
            except Exception as e:
                log_exception(e, context_msg="Failed to remove thumbnail cache")
            self.preview_icon = None
        self.enum = () 


    def get_enum(self, thumb_cache: PreviewsCollection, id: int) -> Tuple[str, str, str, int, int ]:
        self.load_preview(thumb_cache)
        if len(self.enum) == 0:
            name = self.info.name()
            self.enum = ( self.key, name, name, self.preview_icon_id, id )
        else:
            self.enum = ( self.enum[0], self.enum[1], self.enum[2], self.enum[3], id )
        return self.enum


    @property
    def key(self) -> str: return self.info.bin_hash_v2[0]

    @property
    def name(self) -> str: return self.info.name()


    def variants(self) -> List[str]:
        if self.info.pbr:
            if self.info.pbr.variants:
                return [ self.info.pbr.variant_name, *[ e.variant_name for e in self.info.pbr.variants ] ]
        return [ 'Default', ]


    def variant_count(self):
        if self.info.pbr:
            return 1 + len(self.info.pbr.variants)
        else:
            return 1

    def get_bin_hash(self, index: int = 0) -> str: return self.info.get_bin_hash(index)

    @staticmethod
    def load(data: Dict[str, Any]) -> 'TextureEntry':
        return TextureEntry(
            TextureInfo.load(data['info'])
        )

    def save(self) -> Dict[str, Any]:
        return {
            'info': self.info.save()
        }

    def __str__(self) -> str: return self.info.name()
    def __repr__(self) -> str: return self.__str__()
    