from abstract_gui import *
"""
abstract_browser
=================

The `abstract_browser` module is part of the `abstract_gui` module of the `abstract_essentials` package. 
It provides an abstracted mechanism for creating and managing a file/folder browser using PySimpleGUI.

Classes and Functions:
----------------------
- get_scan_browser_layout: Returns the layout for the file/folder scanner window.
- browse_update: Updates values in the browse window.
- return_directory: Returns the current directory or parent directory if a file is selected.
- scan_window: Handles events for the file/folder scanner window.
- forward_dir: Navigate to the given directory.
- scan_directory: Returns the files or folders present in the given directory based on the selected mode.
- get_browse_scan: Initializes the scanner with default settings and runs it.

"""
import os
from . import *
from abstract_utilities import eatAll
def text_to_key(text,additional=None):
    text=eatAll(text,['-'])
    if additional != None:
        text=f"{text} {additional}"
    return f"-{text.upper().replace(' ','_')}-"
def get_event_key_js(event):
    section = event[:-1].split('_')[-1]
    script_event_js = {"event":event,'found':None,'section':section}
    script_event_list = ["-FILES_BROWSER-","-DIR-","-DIRECTORY_BROWSER-","-FILES_LIST-","-SCAN_MODE_ALL-","-SELECT_HIGHLIGHTED-","-SCAN-", "-SELECT_HIGHLIGHTED-", "-MODE-", "-BROWSE_BACKWARDS-", "-BROWSE_FORWARDS-"]
    for script_event in script_event_list:
        conversion = text_to_key(script_event[:-1],additional=section)
        script_event_js[script_event]=conversion
        if event == conversion:
            script_event_js['found']=script_event
    return script_event_js
class AbstractBrowser:
    def __init__(self, window_mgr=None):
        self.window_mgr = window_mgr
        if self.window_mgr and self.window_mgr.window:
            self.window = self.window_mgr.window
        else:
            self.window = sg.Window('File/Folder Scanner', layout=self.get_scan_browser_layout())
        self.event = None
        self.values = None

        self.scan_mode = "all"
        self.history = [os.getcwd()]

    def handle_event(self,values,event,window):
        self.event,self.values,self.window=event,values,window
        self.event_key_js = get_event_key_js(self.event)
        if self.event_key_js['found']:
            return self.while_static(self.window, self.event_key_js, self.values)
        else:
            return self.event, self.values
    def scan_it(self,directory):
        self.last_scan=os.path.isfile(self.values[self.event_key_js['-DIR-']])
        self.scan_results = self.scan_directory(directory, self.scan_mode)
        self.browse_update(key=self.event_key_js['-FILES_LIST-'],args={"values":self.scan_results})
    def get_scan_browser_layout():
        """
        Generate the layout for the file/folder scanning window.

        Returns:
        --------
        list:
            A list of list of PySimpleGUI elements defining the window layout.
        """
        return [
        [make_component("Text",'Directory to scan:'), make_component("InputText",os.getcwd(),key='-DIR-'),
         make_component("FolderBrowse","Folders", enable_events=True, key="directory"),
         make_component("FileBrowse","Files", enable_events=True, key="files"),],
        [make_component("Listbox",[],size=(50, 10),key='-FILES_LIST-',enable_events=True),make_component("Checkbox",'all',default=True,key='-SCAN_MODE_ALL')],
        [make_component("Button","Scan",key="-SCAN-",enable_events=True),
                               make_component("Button","<-",key="<-",enable_events=True),
                               make_component("Button","File Scan Mode",key="-MODE-",enable_events=True),
                               make_component("Button","->",key="->",enable_events=True),
                               make_component("Button",'Select Highlighted',enable_events=True),
                               make_component("Button",'Ok',key='Ok',enable_events=True)]]
    def while_static(self,window,event_key_js,values):
        self.values,self.window=values,window
        if self.event_key_js['found'] == "-FILES_BROWSER-":
            self.browse_update(key=self.event_key_js['-DIR-'],args={"value":self.values[self.event_key_js["-FILES_BROWSER-"]]})
        if self.event_key_js['found'] == "-DIRECTORY_BROWSER-":
            self.browse_update(key=self.event_key_js['-DIR-'],args={"value":self.values[self.event_key_js["-DIRECTORY_BROWSER-"]]})
        if self.event_key_js['found'] == '-SCAN-':
            self.scan_it(self.return_directory())
        if self.event_key_js['found'] == "-SELECT_HIGHLIGHTED-":
            if len(self.values[self.event_key_js['-FILES_LIST-']])>0:
                self.browse_update(key=self.event_key_js['-DIR-'],args={"value":os.path.join(self.return_directory(), self.values[self.event_key_js['-FILES_LIST-']][0])})
        if self.event_key_js['found'] == '-MODE-':
            self.scan_mode = 'folder' if self.scan_mode == 'file' else 'file'
            if self.values['-SCAN_MODE_ALL-']:
                self.scan_mode='all'
            self.window.Element(self.event_key_js['-MODE-']).update(text=f"{self.scan_mode[0].upper()}{self.scan_mode[1:]}  Scan Mode")

        if self.event_key_js['found'] == "-BROWSE_BACKWARDS-":
            # Navigate up to the parent directory
            if self.return_directory() not in self.history:
                self.history.append(self.return_directory())
            directory = os.path.dirname(self.return_directory())  # This will give the parent directory
            self.browse_update(key=self.event_key_js['-DIR-'],args={"value":directory})
            self.browse_update(key=self.event_key_js['-FILES_LIST-'],args={"values":self.scan_directory(directory, self.scan_mode)})
            self.scan_it(directory)
        if self.event_key_js['found'] in ["-BROWSE_FORWARDS-",'-FILES_LIST-']:
            # Navigate down into the selected directory or move to the next history path
            if self.values[self.event_key_js['-FILES_LIST-']]:  # If there's a selected folder in the listbox
                directory = os.path.join(self.return_directory(), self.values[self.event_key_js['-FILES_LIST-']][0])
                if os.path.isdir(directory):
                    self.forward_dir(directory)
                    self.scan_it(directory)
            elif self.history:  # If there's a directory in the history stack
                directory = self.history.pop()
                self.browse_update(key=self.event_key_js['-DIR-'],args={"value":directory})
                self.browse_update(key=self.event_key_js['-FILES_LIST-'],args={"values":self.scan_directory(directory, self.scan_mode)})
        return self.event,self.values
    def return_directory(self):
        """
        Return the current directory or parent directory if a file path is provided.

        Returns:
        --------
        str:
            Directory path.
        """
        directory = self.values[self.event_key_js['-DIR-']]
        if os.path.isfile(self.values[self.event_key_js['-DIR-']]):
            directory = os.path.dirname(self.values[self.event_key_js['-DIR-']])
        if directory == '':
            directory = os.getcwd()
        return directory
    def browse_update(self,key: str = None, args: dict = {}):
        """
        Update specific elements in the browse window.

        Parameters:
        -----------
        window : PySimpleGUI.Window
            The window to be updated. Default is the global `browse_window`.
        key : str, optional
            The key of the window element to update.
        args : dict, optional
            Arguments to be passed for the update operation.
        """
        self.window[key](**args)
    def read_window(self):
        self.event,self.values=self.window.read()
        return self.event,self.values
    def get_values(self):
        if self.values==None:
            self.read_window()
        return self.vaues
    def get_event(self):
        if self.values==None:
            self.read_window()
        return self.event
    def scan_window(self):
        """
        Event handler function for the file/folder scanning window.

        Parameters:
        -----------
        event : str
            Name of the event triggered in the window.
        """
        while True:
            self.read_window()
            if self.event == None:
                break
            while_static(event)
        self.window.close()

    def forward_dir(self,directory):
        """
        Navigate and update the scanner to display contents of the given directory.

        Parameters:
        -----------
        directory : str
            Path to the directory to navigate to.
        """
        if os.path.isdir(directory):
            self.browse_update(key=self.event_key_js['-DIR-'],args={"value":directory})
            self.browse_update(key=self.event_key_js['-FILES_LIST-'],args={"values":self.scan_directory(directory, self.scan_mode)})
    def scan_directory(self,directory_path, mode):
        """
        List files or folders in the given directory based on the provided mode.

        Parameters:
        -----------
        directory_path : str
            Path to the directory to scan.
        mode : str
            Either 'file' or 'folder' to specify what to list.

        Returns:
        --------
        list:
            List of file/folder names present in the directory.
        """
        if mode == 'file':
            return [f for f in os.listdir(directory_path) if os.path.isfile(os.path.join(directory_path, f))]
        elif mode == 'folder':
            return [d for d in os.listdir(directory_path) if os.path.isdir(os.path.join(directory_path, d))]
        return [d for d in os.listdir(directory_path)]
  
    @staticmethod
    def popup_T_F(title:str="popup window",text:str="popup window text"):
        answer = get_yes_no(title=title,text=text)
        if answer == "Yes":
            return True
        return False
    @staticmethod
    def create_new_entity(event:str=None, entity_type:str="Folder"):
        # Retrieve values from the GUI
        if "-ENTITY_TYPE-" in self.values:
            entity_type = self.values["-ENTITY_TYPE-"]
        if event in ["-FOLDER_BROWSE-",'-ENTITY_NAME-']:
            if os.path.isfile(self.values['-ENTITY_NAME-']):
                self.browse_update("-PARENT_DIR-",args={"value":self.get_directory(self.values['-ENTITY_NAME-'])})
                file_name = os.path.basename(self.values['-ENTITY_NAME-'])
                self.browse_update('-ENTITY_NAME-',args={"value":file_name})
        if event == "Create":
            exists =False
            if values['-ENTITY_NAME-'] and self.values['-PARENT_DIR-']:
                entity_path = os.path.join(self.values['-PARENT_DIR-'],self.values['-ENTITY_NAME-'])
                if entity_type == "Folder":
                    exists = os.path.exists(entity_path)  # changed from os.path.dir_exists(entity_path)
                if entity_type == "File":
                    exists = os.path.exists(entity_path)
                if exists:
                    if not popup_T_F(title=f"Override the {entity_type}?",text=f"looks like the {entity_type} path {entity_path} already exists\n did you want to overwrite it?"):
                        return False
                if entity_type == "Folder" and not exists:
                    os.makedirs(entity_path, exist_ok=True)
                elif entity_type == "File":
                    with open(entity_path, 'w') as f:
                        if "save_data" in js_browse_bridge:
                            f.write(self.save_data)  # writes the save_data to the file
                        else:
                            pass  # creates an empty file, or you can handle this differently
                self.browse_update("-FINAL_OUTPUT-",args={"value":entity_path})
                self.browse_update("-SAVE_PROMPT-",args={"visible":True})
                self.window.Element("Cancel").update(text="Exit")

                return "Cancel"
    @staticmethod       
    def save_entity(initial_folder:str=os.getcwd(), entity_type:str="Folder",entity_name:str="",default_prompt:str='Enter the new folder name:',save_data:any=None):
        file_browser_visible = False
        saved_prompt = "Folder Created!!"
        if save_data:
            js_browse_bridge["save_data"] = save_data
            entity_type = "File"
        if entity_type == "File":
            saved_prompt = "File Saved!!"
            if default_prompt == 'Enter the new folder name:':
                default_prompt = 'Enter the new file name or choose from File Browser:'
            file_browser_visible = True
        layout = [
            [get_gui_fun("Text", args={"text": default_prompt})],
            [get_gui_fun("Input", args={"default_text":entity_name,"key": '-ENTITY_NAME-',"enable_events":True}),get_gui_fun("FileBrowse", args={"button_text":"File Browse","key":"-FOLDER_BROWSE-","initial_folder": initial_folder,"enable_events":True,"visible":file_browser_visible})],
            [get_gui_fun("Text", args={"text": 'Select Parent Directory:'})],
            [get_gui_fun("Input", args={"default_text": initial_folder, "key": "-PARENT_DIR-", "disabled": True,"enable_events":True}), 
             get_gui_fun("FolderBrowse", args={"button_text":"Dir Browse","key":"-DIRECTORY_BROWSE-","initial_folder": initial_folder,"enable_events":True})],
            [create_row_of_buttons('Create', {"button_text":'Cancel',"key":"Cancel","enable_events":True}),get_gui_fun("Push"),get_gui_fun("Input", args={"disabled":True,"default_text":entity_type,"key":"-ENTITY_TYPE-","size":(len(entity_type),1)}),get_gui_fun("Input", args={"default_text":"","key":"-FINAL_OUTPUT-","visible":False})],
            [get_gui_fun("Text", args={"text": saved_prompt,"key":"-SAVE_PROMPT-","visible":False})]
        ]
        return self.values['-FINAL_OUTPUT-']
