<filename>Part-03-Understanding-Software-Crafting-Your-Own-Tools/models/edx-platform/common/test/acceptance/pages/lms/tab_nav.py
"""
High-level tab navigation.
"""


from bok_choy.page_object import PageObject
from bok_choy.promise import EmptyPromise, Promise


class TabNavPage(PageObject):
    """
    High-level tab navigation.
    """

    url = None

    # def is_using_v1_style_tabs(self):
    #     return self.q(css='ol.course-tabs').present

    def is_using_boostrap_style_tabs(self):
        return self.q(css='ul.navbar-nav').present

    def is_browser_on_page(self):
        return (self.q(css='ol.course-tabs').present or
                self.q(css='ul.navbar-nav').present)

    def go_to_tab(self, tab_name):
        """
        Navigate to the tab `tab_name`.
        """

        if tab_name not in ['Course', 'Home', 'Discussion', 'Wiki', 'Progress']:
            self.warning(f"'{tab_name}' is not a valid tab name")

        # The only identifier for individual tabs is the link href
        # so we find the tab with `tab_name` in its text.
        tab_css = self._tab_css(tab_name)

        if tab_css is not None:
            self.q(css=tab_css).first.click()
        else:
            self.warning(f"No tabs found for '{tab_name}'")

        self.wait_for_page()
        self._is_on_tab_promise(tab_name).fulfill()

    def _tab_css(self, tab_name):
        """
        Return the CSS to click for `tab_name`.
        If no tabs exist for that name, return `None`.
        """
        all_tabs = self.tab_names

        try:
            tab_index = all_tabs.index(tab_name)
        except ValueError:
            return None
        else:
            if self.is_using_boostrap_style_tabs():
                return f'ul.navbar-nav li:nth-of-type({tab_index + 1}) a'
            else:
                return f'ol.course-tabs li:nth-of-type({tab_index + 1}) a'

    @property
    def tab_names(self):
        """
        Return the list of available tab names.  If no tab names
        are available, wait for them to load.  Raises a `BrokenPromiseError`
        if the tab names fail to load.
        """
        def _standard_check_func():
            tab_names = self.q(css='ol.course-tabs li a').text
            return (len(tab_names) > 0, tab_names)

        def _bootstrap_check_func():
            tab_names = self.q(css='ul.navbar-nav li a').text
            return (len(tab_names) > 0, tab_names)

        if self.is_using_boostrap_style_tabs():
            return Promise(_bootstrap_check_func, "Get all tab names").fulfill()
        else:
            return Promise(_standard_check_func, "Get all tab names").fulfill()

    def _is_on_tab(self, tab_name):
        """
        Return a boolean indicating whether the current tab is `tab_name`.
        This is a private method, so it does NOT enforce the page check,
        which is what we want when we're polling the DOM in a promise.
        """
        if self.is_using_boostrap_style_tabs():
            current_tab_list = self.q(css='ul.navbar-nav > .nav-item.active').text
        else:
            current_tab_list = self.q(css='ol.course-tabs > li > a.active').text

        if len(current_tab_list) == 0:
            self.warning("Could not find current tab")
            return False
        else:
            return current_tab_list[0].strip().split('\n')[0] == tab_name

    def _is_on_tab_promise(self, tab_name):
        """
        Return a `Promise` that the user is on the tab `tab_name`.
        """
        # Use the private version of _is_on_tab to skip the page check
        return EmptyPromise(
            lambda: self._is_on_tab(tab_name),
            f"{tab_name} is the current tab"
        )
