# ---------------------------------------------------------------------------------
# Drop Down Wait Conditions
#
# These are a collection of classes for WebDriverWait specific to drop down lists
#
# --------------------------------------------------------------------------------

from accelarobotkeywords.config.seleniumsettings import SeleniumSettings
from selenium.webdriver.support.select import Select


class DropDownSelectItemByTextValue(object):
    """Condition to select an item in a drop down list by visible text"""
    def __init__(self, locator, text):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value
        self.text = text

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            select.select_by_visible_text(self.text)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class DropDownSelectItemByValue(object):
    """Condition to select an item in a drop down list by value attribute, eg. value="Individual" """
    def __init__(self, locator, value):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value
        self.value = value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            select.select_by_value(self.value)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class DropDownSelectItemByIndex(object):
    """Condition to select an item in a drop down list by index position of the option on the drop down list
     First Item is index 0"""
    def __init__(self, locator, index):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value
        self.index = index

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            select.select_by_visible_text(select.options[int(self.index)].text)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class DropDownGetCurrentlySelectedOptionText(object):
    """Condition to get currently selected option in drop down """

    def __init__(self, locator):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            return select.first_selected_option.text
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class DropDownGetCurrentlySelectedOptionValue(object):
    """Condition to get the value of currently selected option in drop down """

    def __init__(self, locator):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            return select.first_selected_option.get_attribute("value")
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class DropDownGetCurrentlySelectedOptionIndex(object):
    """Condition to get the index of currently selected option, for first item it will return 0 """

    def __init__(self, locator):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            selected_options = select.all_selected_options
            options = select.options
            index = 0
            for option in options:
                for selected_option in selected_options:
                    if option.text == selected_option.text:
                        return index
                index += 1
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class DropDownGetNumberOfOptions(object):
    """Condition to get total number of available options in drop down """

    def __init__(self, locator):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            options = select.options
            return len(options)
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class DropDownGetAllOptions(object):
    """Condition to get All of available options in drop down, it will return a list object  """
    def __init__(self, locator):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value

    def __call__(self, driver):
        try:
            available_options = []
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            select = Select(element)
            options = select.options
            for option in options:
                available_options.append(option.text)
            return available_options
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())