# Copyright (c) 2018-2020, NVIDIA CORPORATION.  All rights reserved.
#
# NVIDIA CORPORATION and its licensors retain all intellectual property
# and proprietary rights in and to this software, related documentation
# and any modifications thereto.  Any use, reproduction, disclosure or
# distribution of this software and related documentation without an express
# license agreement from NVIDIA CORPORATION is strictly prohibited.
# 
import abc
import omni.ui as ui

from typing import Dict
from omni.kit.widget.filebrowser import FileBrowserModel, FileBrowserItem, find_thumbnails_for_files_async
from omni.kit.search_core import AbstractSearchModel, AbstractSearchItem


class SearchDelegate:
    def __init__(self, **kwargs):
        self._search_dir = None

    @property
    def visible(self):
        return True

    @property
    def enabled(self):
        """Enable/disable Widget"""
        return True

    @property
    def search_dir(self):
        return self._search_dir

    @search_dir.setter
    def search_dir(self, search_dir: str):
        self._search_dir = search_dir

    @abc.abstractmethod
    def build_ui(self):
        pass

    @abc.abstractmethod
    def destroy(self):
        pass


class SearchResultsItem(FileBrowserItem):
    class _RedirectModel(ui.AbstractValueModel):
        def __init__(self, search_model, field):
            super().__init__()
            self._search_model = search_model
            self._field = field

        def get_value_as_string(self):
            return str(self._search_model[self._field])

        def set_value(self, value):
            pass

    def __init__(self, search_item: AbstractSearchItem):
        super().__init__(search_item.path, search_item)
        self.search_item = search_item
        self._is_folder = self.search_item.is_folder
        self._models = (
            self._RedirectModel(self.search_item, "name"),
            self._RedirectModel(self.search_item, "date"),
            self._RedirectModel(self.search_item, "size"),
        )

    @property
    def icon(self) -> str:
        """str: Gets/sets path to icon file."""
        return self.search_item.icon

    @icon.setter
    def icon(self, icon: str):
        pass


class SearchResultsModel(FileBrowserModel):
    def __init__(self, search_model: AbstractSearchModel, **kwargs):
        super().__init__(**kwargs)
        self._search_model = search_model
        # Circular dependency
        self._dirty_item_subscription = self._search_model.subscribe_item_changed(self.__on_item_changed)
        self._children = []
        self._thumbnail_dict: Dict = {}

    def destroy(self):
        # Remove circular dependency
        self._dirty_item_subscription = None
        if self._search_model:
            self._search_model.destroy()
        self._search_model = None

    def get_item_children(self, item: FileBrowserItem) -> [FileBrowserItem]:
        """Converts AbstractSearchItem to FileBrowserItem"""
        if self._search_model is None or item is not None:
            return []

        search_items = self._search_model.items or []
        self._children = [SearchResultsItem(search_item) for search_item in search_items]
        if self._filter_fn:
            return list(filter(self._filter_fn, self._children))
        else:
            return self._children

    def __on_item_changed(self, item):
        if item is None:
            self._children = []

        self._item_changed(item)

    async def get_custom_thumbnails_for_folder_async(self, _: SearchResultsItem) -> Dict:
        """
        Returns a dictionary of thumbnails for the given search results.

        Args:
            item (:obj:`FileBrowseritem`): Ignored, should be set to None.

        Returns:
            dict: With item name as key, and fullpath to thumbnail file as value.

        """
        # Files in the root folder only
        file_urls = []
        for item in self.get_item_children(None):
            if item.is_folder or item.path in self._thumbnail_dict:
                # Skip if folder or thumbnail previously found
                pass
            else:
                file_urls.append(item.path)

        thumbnail_dict = await find_thumbnails_for_files_async(file_urls)

        for url, thumbnail_url in thumbnail_dict.items():
            if url and thumbnail_url:
                self._thumbnail_dict[url] = thumbnail_url

        return self._thumbnail_dict
