<gh_stars>10-100
"""Manager implementation for CUI screen for selecting different repositories.
"""

import py_cui
import pyautogit
import pyautogit.commands
import pyautogit.screen_manager
import pyautogit.logger as LOGGER


class RepoSelectManager(pyautogit.screen_manager.ScreenManager):
    """Class representing the manager for the repo select screen

    Attributes
    ----------
    menu_choices : list of str
        Overriden attribute from base class with expanded menu choices.
    """

    def __init__(self, top_manager):
        """Constructor for repo select manager
        """
        
        super().__init__(top_manager, 'repo selection')
        self.menu_choices = ['(Re)Enter Credentials',
                                'Open Directory',
                                'Clone New Repository',
                                'Create New Repository',
                                'Settings',
                                'Enter Custom Command',
                                'Exit']


    def process_menu_selection(self, selection):
        """Override of base class, executes depending on menu selection


        Parameters
        ----------
        selection : str
            The user's menu selection
        """

        if selection == '(Re)Enter Credentials':
            self.manager.ask_credentials()
        elif selection == 'Open Directory':
            # This will be implemented once py_cui adds a filemanager popup.
            self.manager.open_not_supported_popup(selection)
            pass
        elif selection == 'Clone New Repository':
            self.manager.root.move_focus(self.clone_new_box)
        elif selection == 'Create New Repository':
            self.manager.root.move_focus(self.create_new_box)
        elif selection == 'Settings':
            self.manager.open_settings_window()
        elif selection == 'Enter Custom Command':
            self.ask_custom_command()
        elif selection == 'Exit':
            self.manager.close_cleanup()
            exit()
        else:
            self.manager.open_not_supported_popup(selection)


    def initialize_screen_elements(self):
        """Override of base function. Initializes widgets, returns screen widget set

        Returns
        -------
        repo_select_widget_set : py_cui.widget_set.WidgetSet
            Widget set object for repo select screen
        """

        repo_select_widget_set = self.manager.root.create_new_widget_set(5,4)
        
        logo_label = repo_select_widget_set.add_block_label(self.manager.get_logo_text(), 0, 0, column_span=2, center=False)
        logo_label.set_color(py_cui.MAGENTA_ON_BLACK)

        link_label = repo_select_widget_set.add_label('v{} - https://github.com/jwlodek/pyautogit'.format(pyautogit.__version__), 0, 2, column_span=2)
        link_label.add_text_color_rule('https://.*', py_cui.CYAN_ON_BLACK, 'contains', match_type='regex')
        
        self.repo_menu = repo_select_widget_set.add_scroll_menu('Repos in Workspace', 1, 2, row_span=2)
        self.repo_menu.add_item_list(self.manager.repos)
        self.repo_menu.add_key_command(py_cui.keys.KEY_ENTER,   self.manager.open_autogit_window)
        self.repo_menu.add_key_command(py_cui.keys.KEY_SPACE,   self.show_repo_status)
        self.repo_menu.add_key_command(py_cui.keys.KEY_DELETE,  self.ask_delete_repo)
        self.repo_menu.add_key_command(py_cui.keys.KEY_R_LOWER, self.refresh_status)
        self.repo_menu.add_key_command(py_cui.keys.KEY_M_LOWER, self.show_menu)
        self.repo_menu.add_key_command(py_cui.keys.KEY_Q_LOWER, self.manager.clean_exit)
        self.repo_menu.add_key_command(py_cui.keys.KEY_S_LOWER, self.manager.open_settings_window)
        self.repo_menu.add_key_command(py_cui.keys.KEY_C_LOWER, self.manager.ask_credentials)
        self.repo_menu.add_key_command(py_cui.keys.KEY_E_LOWER, self.manager.ask_default_editor)
        self.repo_menu.set_focus_text('Quit - q | Open - Enter | Status - Space | Menu - m | Refresh - r | Delete - Del | Settings - s | Credentials - c | Editor - e')

        self.git_status_box = repo_select_widget_set.add_text_block('Git Repo Status', 1, 0, row_span=4, column_span=2)
        self.git_status_box.set_selectable(False)
        self.git_status_box.add_text_color_rule('Welcome', py_cui.GREEN_ON_BLACK, 'startswith', match_type='line')
        
        self.current_status_box = repo_select_widget_set.add_text_block('Current Status', 1, 3, row_span=2)
        self.current_status_box.set_selectable(False)
        
        self.clone_new_box = repo_select_widget_set.add_text_box('Clone Repository - Enter Remote URL', 3, 2, column_span=2)
        self.clone_new_box.add_key_command(py_cui.keys.KEY_ENTER, lambda : self.execute_long_operation('Cloning', self.clone_new_repo, credentials_required=True))
        
        self.create_new_box = repo_select_widget_set.add_text_box('Create New Repository - Enter Directory Name', 4, 2, column_span=2)
        self.create_new_box.add_key_command(py_cui.keys.KEY_ENTER, self.create_new_repo)
        
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_S_LOWER, self.manager.open_settings_window)
        #repo_select_widget_set.add_key_command(py_cui.keys.KEY_F_LOWER, self.sync_all_repos)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_R_LOWER, self.refresh_status)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_C_LOWER, self.manager.ask_credentials)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_M_LOWER, self.show_menu)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_E_LOWER, self.manager.ask_default_editor)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_A_LOWER, lambda : self.git_status_box.set_text(self.manager.get_about_info()))
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_H_LOWER, lambda : self.git_status_box.set_text(self.manager.get_welcome_message()))

        self.info_panel = self.git_status_box

        self.refresh_status()
        return repo_select_widget_set


    def clear_elements(self):
        """Override of base class function, clears text fields
        """

        self.git_status_box.clear()
        self.clone_new_box.clear()
        self.create_new_box.clear()


    def set_initial_values(self):
        """Override of base function. Sets some initial text for the widgets
        """

        if self.manager.metadata_manager.first_time:
            self.git_status_box.set_text(self.manager.get_welcome_message())
            self.manager.metadata_manager.first_time = False
        else:
            self.git_status_box.set_text(self.manager.get_about_info(with_logo = False))
        self.manager.root.set_status_bar_text('Quit - q | Full Menu - m | Refresh - r | Update Credentials - c | Settings Menu - s')


    def refresh_status(self):
        """Function that refreshes the repositories in the selection screen
        """

        LOGGER.write('Refreshing repo select status')
        self.manager.repos = pyautogit.find_repos_in_path(self.manager.workspace_path)
        self.repo_menu.clear()
        self.repo_menu.add_item_list(self.manager.repos)

        status_message = 'Current directory:\n{}\n\n'.format(self.manager.workspace_path)
        status_message = status_message + '# of Repos: {}\n\n'.format(len(self.manager.repos))
        if len(self.manager.credentials) == 0:
            status_message = status_message + 'Credentials Not Entered\n'
        else:
            status_message = status_message + 'Credentials Entered\n'
        if self.manager.default_editor is not None:
            status_message = status_message + '\nEditor: {}'.format(self.manager.default_editor)
        else:
            status_message = status_message + '\nNo Editor Specified.'
        self.current_status_box.set_text(status_message)


    def ask_delete_repo(self):
        """Function that asks user for confirmation for repo deletion
        """

        target = self.repo_menu.get()
        self.manager.root.show_yes_no_popup("Are you sure you want to delete {}?".format(target), self.delete_repo)


    def delete_repo(self, to_delete):
        """Function that deletes a repo

        Parameters
        ----------
        to_delete : bool
            User's response of request for confirmation of deletion
        """

        if to_delete:
            target = self.repo_menu.get()
            LOGGER.write('Deleting repository {}'.format(target))
            pyautogit.commands.remove_repo_tree(target)
            self.refresh_status()


    def show_repo_status(self):
        """Function that shows the current repository status
        """

        current_repo = self.repo_menu.get_selected_item_index()
        repo_name = self.repo_menu.get()
        LOGGER.write('Displaying repo status for {}'.format(repo_name))
        self.git_status_box.clear()
        out, err = pyautogit.commands.git_status(repo_name)
        if err != 0:
            self.manager.root.show_error_popup('Unable to get git status!', out)
        self.git_status_box.title = 'Git Repo Status - {}'.format(repo_name)
        self.git_status_box.set_text('\n{}'.format(out))
        self.refresh_status()
        self.repo_menu.selected_item = current_repo


    def clone_new_repo(self):
        """Function that clones new repo from given URL
        """

        new_repo_url = self.clone_new_box.get()
        LOGGER.write('Cloning new repo {}'.format(new_repo_url))
        self.message, self.status = pyautogit.commands.git_clone_new_repo(new_repo_url, self.manager.credentials)
        self.refresh_status()
        self.clone_new_box.clear()
        # Turn off loading popup
        self.manager.root.stop_loading_popup()


    def create_new_repo(self):
        """Function that creates a new repo with a given name
        """

        new_dir_target = self.create_new_box.get()
        out, err = pyautogit.commands.git_init_new_repo(new_dir_target)
        if err != 0:
            self.manager.root.show_error_popup('Unable to create new repository!', out)
        else:
            self.manager.root.show_message_popup('Created new repository', out)
        self.create_new_box.clear()
        self.refresh_status()


"""Manager implementation for CUI screen for selecting different repositories.
"""

import py_cui
import pyautogit
import pyautogit.commands
import pyautogit.screen_manager
import pyautogit.logger as LOGGER


class RepoSelectManager(pyautogit.screen_manager.ScreenManager):
    """Class representing the manager for the repo select screen

    Attributes
    ----------
    menu_choices : list of str
        Overriden attribute from base class with expanded menu choices.
    """

    def __init__(self, top_manager):
        """Constructor for repo select manager
        """
        
        super().__init__(top_manager, 'repo selection')
        self.menu_choices = ['(Re)Enter Credentials',
                                'Open Directory',
                                'Clone New Repository',
                                'Create New Repository',
                                'Settings',
                                'Enter Custom Command',
                                'Exit']


    def process_menu_selection(self, selection):
        """Override of base class, executes depending on menu selection


        Parameters
        ----------
        selection : str
            The user's menu selection
        """

        if selection == '(Re)Enter Credentials':
            self.manager.ask_credentials()
        elif selection == 'Open Directory':
            # This will be implemented once py_cui adds a filemanager popup.
            self.manager.open_not_supported_popup(selection)
            pass
        elif selection == 'Clone New Repository':
            self.manager.root.move_focus(self.clone_new_box)
        elif selection == 'Create New Repository':
            self.manager.root.move_focus(self.create_new_box)
        elif selection == 'Settings':
            self.manager.open_settings_window()
        elif selection == 'Enter Custom Command':
            self.ask_custom_command()
        elif selection == 'Exit':
            self.manager.close_cleanup()
            exit()
        else:
            self.manager.open_not_supported_popup(selection)


    def initialize_screen_elements(self):
        """Override of base function. Initializes widgets, returns screen widget set

        Returns
        -------
        repo_select_widget_set : py_cui.widget_set.WidgetSet
            Widget set object for repo select screen
        """

        repo_select_widget_set = self.manager.root.create_new_widget_set(5,4)
        
        logo_label = repo_select_widget_set.add_block_label(self.manager.get_logo_text(), 0, 0, column_span=2, center=False)
        logo_label.set_color(py_cui.MAGENTA_ON_BLACK)

        link_label = repo_select_widget_set.add_label('v{} - https://github.com/jwlodek/pyautogit'.format(pyautogit.__version__), 0, 2, column_span=2)
        link_label.add_text_color_rule('https://.*', py_cui.CYAN_ON_BLACK, 'contains', match_type='regex')
        
        self.repo_menu = repo_select_widget_set.add_scroll_menu('Repos in Workspace', 1, 2, row_span=2)
        self.repo_menu.add_item_list(self.manager.repos)
        self.repo_menu.add_key_command(py_cui.keys.KEY_ENTER,   self.manager.open_autogit_window)
        self.repo_menu.add_key_command(py_cui.keys.KEY_SPACE,   self.show_repo_status)
        self.repo_menu.add_key_command(py_cui.keys.KEY_DELETE,  self.ask_delete_repo)
        self.repo_menu.add_key_command(py_cui.keys.KEY_R_LOWER, self.refresh_status)
        self.repo_menu.add_key_command(py_cui.keys.KEY_M_LOWER, self.show_menu)
        self.repo_menu.add_key_command(py_cui.keys.KEY_Q_LOWER, self.manager.clean_exit)
        self.repo_menu.add_key_command(py_cui.keys.KEY_S_LOWER, self.manager.open_settings_window)
        self.repo_menu.add_key_command(py_cui.keys.KEY_C_LOWER, self.manager.ask_credentials)
        self.repo_menu.add_key_command(py_cui.keys.KEY_E_LOWER, self.manager.ask_default_editor)
        self.repo_menu.set_focus_text('Quit - q | Open - Enter | Status - Space | Menu - m | Refresh - r | Delete - Del | Settings - s | Credentials - c | Editor - e')

        self.git_status_box = repo_select_widget_set.add_text_block('Git Repo Status', 1, 0, row_span=4, column_span=2)
        self.git_status_box.set_selectable(False)
        self.git_status_box.add_text_color_rule('Welcome', py_cui.GREEN_ON_BLACK, 'startswith', match_type='line')
        
        self.current_status_box = repo_select_widget_set.add_text_block('Current Status', 1, 3, row_span=2)
        self.current_status_box.set_selectable(False)
        
        self.clone_new_box = repo_select_widget_set.add_text_box('Clone Repository - Enter Remote URL', 3, 2, column_span=2)
        self.clone_new_box.add_key_command(py_cui.keys.KEY_ENTER, lambda : self.execute_long_operation('Cloning', self.clone_new_repo, credentials_required=True))
        
        self.create_new_box = repo_select_widget_set.add_text_box('Create New Repository - Enter Directory Name', 4, 2, column_span=2)
        self.create_new_box.add_key_command(py_cui.keys.KEY_ENTER, self.create_new_repo)
        
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_S_LOWER, self.manager.open_settings_window)
        #repo_select_widget_set.add_key_command(py_cui.keys.KEY_F_LOWER, self.sync_all_repos)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_R_LOWER, self.refresh_status)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_C_LOWER, self.manager.ask_credentials)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_M_LOWER, self.show_menu)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_E_LOWER, self.manager.ask_default_editor)
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_A_LOWER, lambda : self.git_status_box.set_text(self.manager.get_about_info()))
        repo_select_widget_set.add_key_command(py_cui.keys.KEY_H_LOWER, lambda : self.git_status_box.set_text(self.manager.get_welcome_message()))

        self.info_panel = self.git_status_box

        self.refresh_status()
        return repo_select_widget_set


    def clear_elements(self):
        """Override of base class function, clears text fields
        """

        self.git_status_box.clear()
        self.clone_new_box.clear()
        self.create_new_box.clear()


    def set_initial_values(self):
        """Override of base function. Sets some initial text for the widgets
        """

        if self.manager.metadata_manager.first_time:
            self.git_status_box.set_text(self.manager.get_welcome_message())
            self.manager.metadata_manager.first_time = False
        else:
            self.git_status_box.set_text(self.manager.get_about_info(with_logo = False))
        self.manager.root.set_status_bar_text('Quit - q | Full Menu - m | Refresh - r | Update Credentials - c | Settings Menu - s')


    def refresh_status(self):
        """Function that refreshes the repositories in the selection screen
        """

        LOGGER.write('Refreshing repo select status')
        self.manager.repos = pyautogit.find_repos_in_path(self.manager.workspace_path)
        self.repo_menu.clear()
        self.repo_menu.add_item_list(self.manager.repos)

        status_message = 'Current directory:\n{}\n\n'.format(self.manager.workspace_path)
        status_message = status_message + '# of Repos: {}\n\n'.format(len(self.manager.repos))
        if len(self.manager.credentials) == 0:
            status_message = status_message + 'Credentials Not Entered\n'
        else:
            status_message = status_message + 'Credentials Entered\n'
        if self.manager.default_editor is not None:
            status_message = status_message + '\nEditor: {}'.format(self.manager.default_editor)
        else:
            status_message = status_message + '\nNo Editor Specified.'
        self.current_status_box.set_text(status_message)


    def ask_delete_repo(self):
        """Function that asks user for confirmation for repo deletion
        """

        target = self.repo_menu.get()
        self.manager.root.show_yes_no_popup("Are you sure you want to delete {}?".format(target), self.delete_repo)


    def delete_repo(self, to_delete):
        """Function that deletes a repo

        Parameters
        ----------
        to_delete : bool
            User's response of request for confirmation of deletion
        """

        if to_delete:
            target = self.repo_menu.get()
            LOGGER.write('Deleting repository {}'.format(target))
            pyautogit.commands.remove_repo_tree(target)
            self.refresh_status()


    def show_repo_status(self):
        """Function that shows the current repository status
        """

        current_repo = self.repo_menu.get_selected_item_index()
        repo_name = self.repo_menu.get()
        LOGGER.write('Displaying repo status for {}'.format(repo_name))
        self.git_status_box.clear()
        out, err = pyautogit.commands.git_status(repo_name)
        if err != 0:
            self.manager.root.show_error_popup('Unable to get git status!', out)
        self.git_status_box.title = 'Git Repo Status - {}'.format(repo_name)
        self.git_status_box.set_text('\n{}'.format(out))
        self.refresh_status()
        self.repo_menu.selected_item = current_repo


    def clone_new_repo(self):
        """Function that clones new repo from given URL
        """

        new_repo_url = self.clone_new_box.get()
        LOGGER.write('Cloning new repo {}'.format(new_repo_url))
        self.message, self.status = pyautogit.commands.git_clone_new_repo(new_repo_url, self.manager.credentials)
        self.refresh_status()
        self.clone_new_box.clear()
        # Turn off loading popup
        self.manager.root.stop_loading_popup()


    def create_new_repo(self):
        """Function that creates a new repo with a given name
        """

        new_dir_target = self.create_new_box.get()
        out, err = pyautogit.commands.git_init_new_repo(new_dir_target)
        if err != 0:
            self.manager.root.show_error_popup('Unable to create new repository!', out)
        else:
            self.manager.root.show_message_popup('Created new repository', out)
        self.create_new_box.clear()
        self.refresh_status()
Manager implementation for CUI screen for selecting different repositories. Class representing the manager for the repo select screen      Attributes     ----------     menu_choices : list of str         Overriden attribute from base class with expanded menu choices. Constructor for repo select manager Override of base class, executes depending on menu selection           Parameters         ----------         selection : str             The user's menu selection # This will be implemented once py_cui adds a filemanager popup. Override of base function. Initializes widgets, returns screen widget set          Returns         -------         repo_select_widget_set : py_cui.widget_set.WidgetSet             Widget set object for repo select screen #repo_select_widget_set.add_key_command(py_cui.keys.KEY_F_LOWER, self.sync_all_repos) Override of base class function, clears text fields Override of base function. Sets some initial text for the widgets Function that refreshes the repositories in the selection screen Function that asks user for confirmation for repo deletion Function that deletes a repo          Parameters         ----------         to_delete : bool             User's response of request for confirmation of deletion Function that shows the current repository status Function that clones new repo from given URL # Turn off loading popup Function that creates a new repo with a given name