# -----------------------------------------------------------------------
# Element Wait Conditions
#
# These are a collection of classes for WebDriverWait specific to Elements
#
# ------------------------------------------------------------------------

import os

from selenium.common.exceptions import *
from accelarobotkeywords.config.seleniumsettings import SeleniumSettings
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.common.action_chains import ActionChains


class ElementEnterText(object):
    """
    An expected condition for entering text into an element
    """

    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)
            element.clear()
            element.send_keys(self.text)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementEnterTextAndCheckValueAttribute(object):
    """
    An expected condition for entering text into an element and checking value attribute
    """

    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)
            element.clear()
            element.send_keys(self.text)
            actual_value = element.get_attribute('value')
            if actual_value is None:
                actual_value = ''
            return actual_value.strip() == self.text
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementTypeTextIndividually(object):
    """
    An expected condition for entering text into an element by typing individual characters
    """

    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)
            element.clear()
            for char in self.text:
                element.send_keys(char)
            actual_text = element.text
            actual_value = element.get_attribute('value')
            if actual_text is None:
                actual_text = ''
            if actual_value is None:
                actual_value = ''
            return actual_text.strip() == self.text or actual_value.strip() == self.text
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementEnterTextWithNoClear(object):
    """
    An expected condition for entering text into an element with no clear
    """

    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)
            element.send_keys(self.text)
            actual_text = element.text
            actual_value = element.get_attribute('value')
            if actual_text is None:
                actual_text = ''
            if actual_value is None:
                actual_value = ''
            return actual_text.strip() == self.text or actual_value.strip() == self.text
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementEnterTextViaJavascript(object):
    """
    An expected condition for entering text into an element via javascript
    """

    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)
            driver.execute_script('arguments[0].value=arguments[1];', element, self.text)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementEnterTextToAllMatching(object):
    """
    An expected condition for entering text to all matching elements
    """

    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)
            elements = driver.find_elements(self.locator_type, self.locator_value)
            for element in elements:
                element.send_keys(self.text)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementClearTextToAllMatching(object):
    """
    An expected condition for clearing text from all matching elements
    """

    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)
            elements = driver.find_elements(self.locator_type, self.locator_value)
            for element in elements:
                element.clear()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementEnterTextViaActions(object):
    """
    An expected condition for entering text into an element via actions
    """

    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)
            ActionChains(driver).click(element).send_keys(Keys.HOME).send_keys(self.text).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementClearText(object):
    """
    An expected condition for clearing text from an element
    """

    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)
            element.clear()
            actual_text = element.text
            actual_value = element.get_attribute('value')
            if actual_text is None:
                actual_text = ''
            if actual_value is None:
                actual_value = ''
            return actual_text.strip() == '' or actual_value.strip() == ''
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementSendAnyKey(object):
    """
    An expected condition for sending a specified special key to an element
    """

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

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            ActionChains(driver).click(element).send_keys(self.key).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementSendEscapeKey(object):
    """
    An expected condition for sending Escape key to currently active element
    """

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)

            ActionChains(driver).click(driver.switch_to.active_element).send_keys(Keys.ESCAPE).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementDoubleClick(object):
    """
    An expected condition for double clicking on an element
    """

    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)
            ActionChains(driver).move_to_element(element).double_click(element).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementLeftClick(object):
    """
    An expected condition for left clicking on an element
    """

    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)
            element.click()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementWaitForDisplayed(object):
    """
    An expected condition for waiting for a displayed element
    """

    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)
            return element.is_displayed()
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementWaitForNotDisplayed(object):
    """
    An expected condition for waiting for a not displayed element
    """

    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)
            return not element.is_displayed()
        except NoSuchElementException:
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementWaitForEnabled(object):
    """
    An expected condition for waiting for an element to be enabled
    """

    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)
            return element.is_enabled()
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementWaitForNotEnabled(object):
    """
    An expected condition for waiting for an element to be not enabled
    """

    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)
            return not element.is_enabled()
        except NoSuchElementException:
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementShouldBeEnabled(object):
    """
    An expected condition for verifying that an element is enabled
    """

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

    def __call__(self, driver):
        try:
            element = driver.find_element(self.locator_type, self.locator_value)
            return element.is_enabled()
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementShouldNotBeEnabled(object):
    """
    An expected condition for verifying that an element is not enabled
    """

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

    def __call__(self, driver):
        try:
            element = driver.find_element(self.locator_type, self.locator_value)
            return not element.is_enabled()
        except NoSuchElementException:
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementShouldBeDisplayed(object):
    """
    An expected condition for verifying that an element is displayed
    """

    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)
            return element.is_displayed()
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementShouldNotBeDisplayed(object):
    """
    An expected condition for verifying that an element is not displayed
    """

    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)
            return not element.is_displayed()
        except NoSuchElementException:
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())

class ElementShouldBeEmpty(object):
    """
    An expected condition for verifying that an element is empty
    """

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

    def __call__(self, driver):
        try:
            element = driver.find_element(self.locator_type, self.locator_value)
            actual_text = element.text
            actual_value = element.get_attribute('value')
            if actual_text is None:
                actual_text = ''
            if actual_value is None:
                actual_value = ''
            return actual_text.strip() == '' and actual_value.strip() == ''
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementHoverAndLeftClick(object):
    """
    An expected condition to hover over and click on an element
    """

    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)
            ActionChains(driver).move_to_element(element).click().perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetText(object):
    """
    An expected condition to get the text of an element
    Returns a String containing the elements text
    """

    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)
            element_text = element.text
            return element_text.strip()
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetTextFromAllMatchingElements(object):
    """
    An expected condition to get text from all matching elements
    Returns a List containing all text strings found for matching elements
    """

    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)
            elements = driver.find_elements(self.locator_type, self.locator_value)
            text_list = []
            for element in elements:
                element_text = element.text
                text_list.append(element_text.strip())
            return text_list
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetAttributeFromAllMatchingElements(object):
    """
    An expected condition to get attribute values from all matching elements
    Returns a List containing all attribute value strings found for matching elements
    """

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

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            elements = driver.find_elements(self.locator_type, self.locator_value)
            attribute_values_list = []
            for element in elements:
                element_attribute_text = element.get_attribute(self.attribute_name)
                attribute_values_list.append(element_attribute_text.strip())
            return attribute_values_list
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetTextFromChildElements(object):
    """
    An expected condition to get text from specified child element(s) of a parent locator
    Returns a List containing all text strings from child elements
    """

    def __init__(self, parent_locator, child_locator):
        self.parent_locator_type = parent_locator.locator_type
        self.parent_locator_value = parent_locator.locator_value
        self.child_locator_type = child_locator.locator_type
        self.child_locator_value = child_locator.locator_value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            elements = driver.find_elements(self.parent_locator_type, self.parent_locator_value)
            text_list = []
            for element in elements:
                element_text = element.find_element(self.child_locator_type, self.child_locator_value).text
                text_list.append(element_text.strip())
            return text_list
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetTextFromAllChildElements(object):
    """
    An expected condition to get text from all child element(s) of a parent locator
    Returns a List containing all text strings from child elements
    """

    def __init__(self, parent_locator):
        self.parent_locator_type = parent_locator.locator_type
        self.parent_locator_value = parent_locator.locator_value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            elements = driver.find_elements(self.parent_locator_type, self.parent_locator_value)
            text_list = []
            for element in elements:
                element_text = element.text
                text_list.append(element_text.strip())
            return text_list
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetAttribute(object):
    """
    An expected condition to get the attribute of an element based on its name
    Returns a String containing the element attribute's value
    """

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

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            element_attribute = element.get_attribute(self.attribute_name)
            return element_attribute.strip()
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementMakeVisible(object):
    """
    An expected condition for making a hidden element visible via javascript
    """

    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)
            driver.execute_script('arguments[0].style = ""; arguments[0].style.display = "block"; arguments['
                                  '0].style.visibility = "visible";', element)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementMakeHidden(object):
    """
    An expected condition for making an element hidden via javascript
    """

    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)
            driver.execute_script('arguments[0].style = ""; arguments[0].style.display = "none"; arguments['
                                  '0].style.visibility = "hidden";', element)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementClickNthElement(object):
    """
    An expected condition Click on nth position element,
    if a locator has multiple matching element, it will click on the element based on the
    index(nth position ) passed in
    """

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

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            elements = driver.find_elements(self.locator_type, self.locator_value)
            elements[self.nth_position].click()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementControlAndLeftClick(object):
    """
    An expected condition to Control and left click on an element
    ctrl + Left click
    """

    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)
            ActionChains(driver).key_down(Keys.CONTROL).click(element).key_up(Keys.CONTROL).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementControlAndRightClick(object):
    """
    An expected condition to Control and Right click on an element
    ctrl + Right click
    """

    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)
            ActionChains(driver).key_down(Keys.CONTROL).context_click(element).key_up(Keys.CONTROL).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementControlAndPressKey(object):
    """
    An expected condition to Control and Press a key on the in focus element
    ctrl + press a,v,x,b key
    """

    def __init__(self, key):
        self.key = key

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            ActionChains(driver).key_down(Keys.CONTROL).send_keys(self.key).key_up(Keys.CONTROL).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementAltAndPressKey(object):
    """
    An expected condition to Alt and Press a key on the in focus element
    Alt + press key
    """

    def __init__(self, key):
        self.key = key

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            ActionChains(driver).key_down(Keys.ALT).send_keys(self.key).key_up(Keys.ALT).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementJsClick(object):
    """
    An expected condition to JS click (javascript click ) on an element
    """

    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)
            driver.execute_script("arguments[0].click();", element)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetTotalNumberOfElements(object):
    """
    An expected condition to get total number of elements on a locator
    """
    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)
            elements = driver.find_elements(self.locator_type, self.locator_value)
            return str(len(elements))
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementSetFocus(object):
    """
    An expected condition to set focus on an element
    """
    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)
            element.send_keys(Keys.NULL)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetActiveElement(object):
    """
    An expected condition to get currently active/focused element
    """

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            elem = driver.switch_to.active_element
            return elem
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementSetAttributeValueByJS(object):
    """
    An expected condition to set attribute value by js: the attribute and value both are passed in
    """
    def __init__(self, locator, attribute, value):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value
        self.attribute = attribute
        self.value = value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            script = ("arguments[0].%s=arguments[1];" % self.attribute)
            driver.execute_script(script, element, self.value)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementMouseOver(object):
    """
    An expected condition to move mouse over to the element
    """

    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)
            ActionChains(driver).move_to_element(element).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementGetCSSPropertyValue(object):
    """
    An expected condition to Get value of css property. eg. font-size
    """
    def __init__(self, locator, css_property):
        self.locator_type = locator.locator_type
        self.locator_value = locator.locator_value
        self.css_property = css_property

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            css_value = driver.find_element(self.locator_type, self.locator_value).value_of_css_property(self.css_property)
            return str(css_value)
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementDragAndDrop(object):
    """
    An expected condition drag and drop element to another element
    """
    def __init__(self, locator_from, locator_to):
        self.locator_from_type = locator_from.locator_type
        self.locator_from_value = locator_from.locator_value
        self.locator_to_type = locator_to.locator_type
        self.locator_to_value = locator_to.locator_value

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element_from = driver.find_element(self.locator_from_type, self.locator_from_value)
            element_to = driver.find_element(self.locator_to_type, self.locator_to_value)
            ActionChains(driver).click_and_hold(element_from).perform()
            ActionChains(driver).move_to_element(element_to).perform()
            ActionChains(driver).release(element_to).perform()
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementDragAndDropXYPosition(object):
    """
    An expected condition drag and drop an element to x,y offset
    """
    def __init__(self, locator_from, x_offset, y_offset):
        self.locator_from_type = locator_from.locator_type
        self.locator_from_value = locator_from.locator_value
        self.x_offset = int(x_offset)
        self.y_offset = int(y_offset)

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element_from = driver.find_element(self.locator_from_type, self.locator_from_value)
            ActionChains(driver).drag_and_drop_by_offset(element_from, self.x_offset, self.y_offset)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ElementChooseFile(object):
    """
    An expected condition for entering text into a choose file input element
    """

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

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            self.info('Sending %s to browser.' % os.path.abspath(self.text))
            element = driver.find_element(self.locator_type, self.locator_value)
            element.clear()
            element.send_keys(self.text)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())


class ScrollToElementViaJavascript(object):
    """
    An expected condition for scrolling to an element via javascript
    """

    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)
            driver.execute_script('arguments[0].scrollIntoView(true);', element)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())

class JsScriptExecutor(object):
    """
    For a general script to be executed
    """
    def __init__(self, js_script):
        self.js_script = js_script

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            driver.execute_script(self.js_script)
            return True
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())

class ElementGetCssValue(object):
    """
    An expected condition to get the css value of an element
    Returns a String containing the elements css value
    """

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

    def __call__(self, driver):
        try:
            driver.implicitly_wait(1)
            element = driver.find_element(self.locator_type, self.locator_value)
            element_text = element.getCssValue(self.css_value)
            return element_text.strip()
        except Exception:
            return False
        finally:
            driver.implicitly_wait(SeleniumSettings.get_implicit_wait())