import omni
import os
import omni.client

from omni.kit.widget.prompt import PromptManager, PromptButtonInfo
from typing import List, Tuple, Callable
from omni.kit.widget.filebrowser import FileBrowserItem
from .filebrowser import FileBrowserMode, FileBrowserSelectionType
from .filebrowser.app_filebrowser import FileBrowserUI


class FilePicker:
    def __init__(
        self,
        title: str,
        mode: FileBrowserMode,
        file_type: FileBrowserSelectionType,
        filter_options: List[Tuple[str, str]],
        save_extensions: List[str] = [],
        allow_multi_selections=False,
        options_pane_build_fn: Callable[[List[str]], bool] = None,
        on_selection_changed: Callable[[List[str]], bool] = None,
        **kwargs
    ):
        self._mode = mode
        self._app = omni.kit.app.get_app()
        self._open_handler = None
        self._cancel_handler = None
        if self._mode == FileBrowserMode.SAVE:
            self._allow_multi_selections = False
        else:
            self._allow_multi_selections = allow_multi_selections

        self._options_pane_build_fn = options_pane_build_fn
        self._on_selection_changed = on_selection_changed
        if self._options_pane_build_fn:
            build_fn = self._build_options_pane
        else:
            build_fn = None

        if self._on_selection_changed:
            selection_fn = self._selection_changed
        else:
            selection_fn = None

        self._ui_handler = FileBrowserUI(
            title, mode, file_type, filter_options, save_extensions, self._allow_multi_selections, build_fn, selection_fn, **kwargs
        )
        self._prompt = None

    def _selection_changed(self, paths: List[FileBrowserItem]):
        to_convert_paths = []
        for path_item in paths:
            if isinstance(path_item, FileBrowserItem):
                if path_item.is_folder:
                    continue

                to_convert_paths.append(path_item.path)
            else:
                to_convert_paths.append(path_item)

        if self._on_selection_changed:
            self._on_selection_changed(to_convert_paths)

    def _build_options_pane(self, paths: List[FileBrowserItem]):
        to_convert_paths = []
        for path_item in paths:
            if isinstance(path_item, FileBrowserItem):
                if path_item.is_folder:
                    continue

                to_convert_paths.append(path_item.path)
            else:
                to_convert_paths.append(path_item)

        if self._options_pane_build_fn:
            return self._options_pane_build_fn(to_convert_paths)
        else:
            return False

    def _save_and_prompt_if_exists(self, file_path: str, file_save_handler: Callable[[str, bool], None] = None):
        result, _ = omni.client.stat(file_path)
        existed = result == omni.client.Result.OK
        if existed:
            PromptManager.post_simple_prompt(
                f'{omni.kit.ui.get_custom_glyph_code("${glyphs}/exclamation.svg")} Overwrite',
                f"File {os.path.basename(file_path)} already exists, do you want to overwrite it?",
                ok_button_info=PromptButtonInfo("YES", lambda: file_save_handler(file_path, True)),
                cancel_button_info=PromptButtonInfo("No")
            )
        elif file_save_handler:
            file_save_handler(file_path, False)

    def _on_file_open(self, paths: List[str]):
        if not paths:
            return

        def file_open(paths: List[str], overwrite: bool):
            if not self._open_handler:
                return
            
            self._open_handler(paths, overwrite)

        if self._mode == FileBrowserMode.SAVE:
            self._save_and_prompt_if_exists(paths[-1], lambda path, overwrite: file_open([path], overwrite))
        else:
            file_open(paths, False)

    def _on_cancel_open(self):
        if self._cancel_handler:
            self._cancel_handler()

    def set_file_selected_fn(self, file_open_handler: Callable[[List[str], bool], None]):
        self._open_handler = file_open_handler

    def set_cancel_fn(self, cancel_handler: Callable[[], None]):
        self._cancel_handler = cancel_handler

    def show(self, dir: str = None, filename: str = None):
        if self._ui_handler:
            if dir:
                self._ui_handler.set_current_directory(dir)

            if filename:
                self._ui_handler.set_current_filename(filename)
            self._ui_handler.open(self._on_file_open, self._on_cancel_open)
    
    def hide(self):
        if self._ui_handler:
            self._ui_handler.hide()

    def set_current_directory(self, dir: str):
        if self._ui_handler:
            self._ui_handler.set_current_directory(dir)

    def set_current_filename(self, filename: str):
        if self._ui_handler:
            self._ui_handler.set_current_filename(filename)
    
    def get_current_filename(self):
        if self._ui_handler:
            return self._ui_handler.get_current_filename()

        return None

    def destroy(self):
        self._options_pane_build_fn = None
        self._on_selection_changed = None
        if self._prompt:
            self._prompt.destroy()
        self._prompt = None
        self._open_handler = None
        self._cancel_handler = None
        if self._ui_handler:
            self._ui_handler.destroy()
        self._ui_handler = None
