class _AssertionKeywords(KeywordGroup):

    def __init__(self):
        self._pattern_finder = PatternFinder()

    # Public
    
    def assert_pattern_is_visible_in_active_app(self, pattern):
        """Assert that ``pattern`` is visible in search region
        See `introduction` for details about locating elements.

        Note this keyword automatically searches on region of the app in focus and may be paired with the
        keyword Set Application Focus.

        See also `Assert Pattern Is Not Visible In Active App`, `Assert Pattern Is Not Visible In Region`, 
        and `Assert Pattern Is Visible In Region`.

        Example:
        | Set Application Focus                   | Calculator       |
        | Assert Pattern Is Visible in Active App | equalsbutton.png |
        # Asserts that pattern is visible in the new search region in active app as defined by offset values.
        """
        self._info("Asserting that pattern, '%s' is visible in app." % (pattern))
        self.set_search_region_to_active_app()
        try:
            assert exists(self._pattern_finder._find_pattern(pattern))
        except AssertionError, err:
            raise AssertionError("No matching pattern: %s found in search region." % (pattern))
class _WaitingKeywords(KeywordGroup):
    def __init__(self):
        self._pattern_finder = PatternFinder()
        self.sikulix_timeout = None
        self.sikulix_scanrate = None

    # Public

    def set_sikulix_timeout(self, timeout):
        """Sets the ``sikulix timeout`` value.

        See `introduction` for details about `sikulix_timeout`.
        """
        if self.sikulix_timeout is not None:
            self.sikulix_timeout = float(self._clean_string(timeout))

        self._info("Setting sikulix timeout to '%s' seconds." % (self.sikulix_timeout))
        Settings.AutoWaitTimeout = self.sikulix_timeout

    def set_sikulix_scanrate(self, scanrate):
        """Sets the ``sikulix scanrate`` value.

        See `introduction` for details about `sikulix_scanrate`.
        """
        if self.sikulix_scanrate is not None:
            self.sikulix_scanrate = float(self._clean_string(scanrate))

        self._info("Setting sikulix scanrate to '%s' seconds." % (self.sikulix_scanrate))
        Settings.WaitScanRate = self.sikulix_scanrate

    def wait_in_seconds(self, timeout):
        """Waits until ``timeout`` expires.

        See also `Wait For Pattern To Be Visible`, `Wait Until Pattern Is Visible`, 
        `Wait For Pattern To Vanish` and `Wait Until Pattern Vanish`.
        """
        timeout = float(self._clean_string(timeout))
        self._info("Setting wait value to '%s' seconds." % (timeout))
        wait(timeout)

    def wait_for_pattern_to_be_visible(self, pattern):
        """Waits until ``pattern`` appears on `application` in focus. 
        Fails if ``pattern`` is not immediately visible on `application` in focus.
        SikuliX's default timeout is 3 seconds.

        See also `Wait In Seconds`, `Wait Until Pattern Is Visible`, 
        `Wait For Pattern To Vanish` and `Wait Until Pattern Vanish`.
        """
        self.set_search_region_to_active_app()
        self._info("Waiting for pattern '%s' to be visible." % (pattern))
        try:
            pattern = self._pattern_finder._find_pattern(pattern)
            wait(pattern)
        except FindFailed, err:
            raise AssertionError("Element locator '%s' did not match any elements" % (pattern))
 def __init__(self):
     self._pattern_finder = PatternFinder()
     self.sikulix_timeout = None
     self.sikulix_scanrate = None
 def __init__(self):
     self._pattern_finder = PatternFinder()
class _ElementKeywords(KeywordGroup):
    def __init__(self):
        self._pattern_finder = PatternFinder()

    # Public

    """***************************** MOUSE ACTIONS ************************************
    Performs mouse actions on matching pattern that will serve as locators.
    Search region or setROI() value is set to the application in focus as default.
    Locators or patterns must be any of the following format: <image.png>, <image.png> = <sensitivity from 0.00 to 0.99>, <string>
    For example:
    |  Click Pattern    freelancerlogo.png = 0.90
    |  Click Pattern    freelancerlogo.png
    |  Click Pattern    Password
    """

    def click_region(self):
        """Left-clicks the center x,y coordinate of a specified ROI or search region.

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Double Click Region`, `Right Click Region`, `Get Text In Search Region`, `Hover At Region`
        and `Highlight Region`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app.            |
        | Click Region                        |                   | # Clicks the center of the specified ROI or search region. |
        """
        reg = self.get_last_matching_region()
        self._info("Clicking specified ROI or search region '%s'" % (reg))
        reg.click()

    def double_click_region(self):
        """Double-clicks the center x,y coordinate of a specified ROI or search region.

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Click Region`, `Right Click Region`, `Get Text In Search Region`, `Hover At Region`
        and `Highlight Region`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app.                   |
        | Double Click Region                 |                   | # Double-clicks the center of the specified ROI or search region. |
        """
        reg = self.get_last_matching_region()
        self._info("Double-clicking specified ROI or search region '%s'" % (reg))
        reg.doubleClick()

    def right_click_region(self):
        """Right-clicks the center x,y coordinate of a specified ROI or search region.

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Click Region`, `Double Click Region`, `Get Text In Search Region`, `Hover At Region`
        and `Highlight Region`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app.                   |
        | Right Click Region                  |                   | # Right-clicks the center of the specified ROI or search region. |
        """
        reg = self.get_last_matching_region()
        self._info("Right-clicking specified ROI or search region '%s'" % (reg))
        reg.rightClick()

    def highlight_region(self, highlight_duration):
        """Highlights the specified ROI or search region for a specified ``highlight_duration`` in seconds.

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Click Region`, `Double Click Region`, `Right Click Region`, `Hover At Region` and `Get Text In Search Region`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app.                 |
        | Highlight Region                    | 2                 | # Highlights the specified ROI or search region. for 2 seconds. |
        """
        reg = self.get_last_matching_region()
        self._info("Highlighting specified ROI or search region '%s' for '%s' seconds" % (reg, highlight_duration))
        reg.highlight(float(highlight_duration))

    def hover_at_region(self):
        """Hovers mouse pointer at center x,y coordinate of a specified ROI or search region.

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Double Click Region`, `Right Click Region`, `Get Text In Search Region`
        and `Highlight Region`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app. |
        | Hover At Region                     |                   | # Hovers mouse pointer at the center of specified ROI or search region. |
        """
        reg = self.get_last_matching_region()
        self._info("Hovering at specified ROI or search region '%s'" % (reg))
        reg.hover()

    def type_text_at_region(self, text):
        """Types `text` at x,y coordinate of a specified ROI or search region.

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Paste Text At Region`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app. |
        | Type Text At Region                 |  Hello World!     | # Types 'Hello World!' at specified ROI or search region. |
        """
        text = text.strip()
        reg = self.get_last_matching_region()
        self._info("Typing text '%s' at specified ROI or search region '%s'" % (text, reg))
        reg.type(text)

    def paste_text_at_region(self, text):
        """Pastes `text` at x,y coordinate of a specified ROI or search region.

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Type Text At Region`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app. |
        | Paste Text At Region                 |  Hello World!    | # Pastes 'Hello World!' at specified ROI or search region. |
        """
        text = text.strip()
        reg = self.get_last_matching_region()
        self._info("Pasting text '%s' at specified ROI or search region '%s'" % (text, reg))
        reg.paste(text)

    def click_last_match(self):
        """Left-clicks the center x,y coordinate of a last match.

        See also `Double Click Last Match`, `Right Click Last Match`, `Hover At Last Match`
        and `Highlight Last Match`.

        Example:
        | Click Last Match  | # Clicks the last matched pattern. |
        """
        self._info("Clicking last matched pattern.")
        click()

    def double_click_last_match(self):
        """Double-clicks the center x,y coordinate of a last match.

        See also `Click Last Match`, `Right Click Last Match`, `Hover At Last Match`
        and `Highlight Last Match`.

        Example:
        | Double Click Last Match  | # Double-clicks the last matched pattern. |
        """
        self._info("Double-clicking last matched pattern.")
        doubleClick()

    def right_click_last_match(self):
        """Right-clicks the center x,y coordinate of a last match.

        See also `Click Last Match`, `Double Click Last Match`, `Hover At Last Match`
        and `Highlight Last Match`.

        Example:
        | Right Click Last Match  | # Right-clicks the last matched pattern. |
        """
        self._info("Right-clicking last matched pattern.")
        rightClick()

    def hover_at_last_match(self):
        """Double-clicks the center x,y coordinate of a last match.

        See also `Click Last Match`, `Double Click Last Match`, `Right Click Last Match`, `Hover At Last Match`
        and `Highlight Last Match`.

        Example:
        | Hover At Last Match  | # Hovers at the last matched pattern. |
        """
        self._info("Hovering at last matched pattern.")
        hover()

    def click_pattern(self, pattern):
        """Perform a mouse `click` on the click point using the `left` button.
        Click point is at the `center` of the element identified by ``pattern``.

        Key attributes for arbitrary patterns are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Clicking element '%s'." % pattern)
        self._pattern_find(pattern, None, None).click()

    def click_pattern_at_coordinates(self, pattern, xoffset, yoffset):
        """Perform a mouse `click` on the click point using the `left` button.
        Click point is at `x/y` coordinates of the element identified by ``pattern``.

        Key attributes for arbitrary patterns are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Click element '%s' in coordinates '%s', '%s'." % (pattern, xoffset, yoffset))
        self._pattern_find(pattern, xoffset, yoffset).click()

    def right_click_pattern(self, pattern):
        """Perform a mouse `click` on the click point using the `right` button.
        Click point is at the `center` of the element identified by ``pattern``.

        Key attributes for arbitrary patterns are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Right-clicking element '%s'." % pattern)
        self._pattern_find(pattern, None, None).rightClick()

    def right_click_pattern_at_coordinates(self, pattern, xoffset, yoffset):
        """Perform a mouse `click` on the click point using the `right` button.
        Click point is at `x/y` coordinates of the element identified by ``pattern``.

        Key attributes for arbitrary patterns are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Right-clicking element '%s' in coordinates '%s', '%s'." % (pattern, xoffset, yoffset))
        self._pattern_find(pattern, xoffset, yoffset).rightClick()

    def double_click_pattern(self, pattern):
        """Perform a mouse `double-click` on the click point using the `left` button.
        Click point is at the `center` of the element identified by ``pattern``.

        Key attributes for arbitrary patterns are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Double-clicking element '%s'." % pattern)
        self._pattern_find(pattern, None, None).doubleClick()

    def double_click_pattern_at_coordinates(self, pattern, xoffset, yoffset):
        """Perform a mouse `double-click` on the click point using the `left` button.
        Click point is at `x/y` coordinates of the element identified by ``pattern``.

        Key attributes for arbitrary patterns are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Double-clicking element '%s' in coordinates '%s', '%s'." % (pattern, xoffset, yoffset))
        self._pattern_find(pattern, xoffset, yoffset).doubleClick()

    def highlight_pattern(self, pattern, highlight_duration):
        """Highlight element identified by ``pattern`` for a specified ``highlight_duration`` in seconds.

        Key attributes for arbitrary ``patterns`` are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.

        Example:
        | Highlight Pattern | pattern.png = 0.90 | 2   | This is a sample text. | # Type a text in element identified by pattern.png |
        """
        self._info("Highlighting element '%s' for '%s' second(s)." % (pattern, highlight_duration))
        self._pattern_find(pattern, None, None).highlight(float(highlight_duration))

    def hover_at_pattern(self, pattern):
        """Hover mouse pointer at center of element identified by ``pattern``.

        Key attributes for arbitrary ``patterns`` are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Hovering at element '%s'." % pattern)
        self._pattern_find(pattern, None, None).hover()

    def hover_at_pattern_at_coordinates(self, pattern, xoffset, yoffset):
        """Hover mouse pointer at `x/y` coordinates of the element identified by ``pattern``.

        Key attributes for arbitrary ``patterns`` are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        """
        self._info("Hovering at element '%s' in coordinates '%s', '%s'." % (pattern, xoffset, yoffset))
        self._pattern_find(pattern, xoffset, yoffset).hover()

    def move_mouse_at_coordinates(self, xoffset, yoffset):
        """Move mouse cursor coordinates at ``x/y`` coordinates of the `screen`.
        """
        self._info("Moving mouse at coordinates '%s', '%s'." % (xoffset, yoffset))
        mouseMove(int(xoffset), int(yoffset))

    def mouse_button_down(self, mouse_button):
        """Press the ``left`` mouse button `down`. 
        Must be paired with `Mouse Button Up` keyword.
        """
        self._info("Mouse down at, '%s' button." % (mouse_button))
        mouseDown(self._mouse_button(mouse_button))

    def mouse_button_up(self, mouse_button):
        """Release the mouse button previously pressed. 
        Must be paired with `Mouse Button Down` keyword.
        """
        self._info("Mouse up at, '%s' button." % (mouse_button))
        mouseUp(self._mouse_button(mouse_button))

    def scroll_from_pattern(self, pattern, scroll):
        """Scroll up or down as specified by the `scroll step` at center of the element identified by ``pattern``.
        Key attributes for arbitrary ``patterns`` are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.

        Examples:
        | Scroll From Pattern | Up = 10   | # Scroll up 10 steps. |
        | Scroll From Pattern | Down = 10 | # Scroll down 10 steps. |
        """
        self.hover_at_pattern(pattern)
        self._info("Scrolling '%s' in pattern '%s'." % (scroll, pattern))
        self._scroll_direction_and_steps_from_pattern(pattern, scroll, None, None)

    def scroll_from_pattern_at_coordinates(self, pattern, scroll, xoffset, yoffset):
        """Scroll up or down as specified by the `scroll` step at `x/y` coordinates of the element identified by ``pattern``.

        Key attributes for arbitrary ``patterns`` are `images` which is advisably in PNG format or `strings`. 
        See `introduction` for details about locating elements.
        
        Examples:
        | Scroll From Pattern At Coordinates | pattern.png = 0.80 | Up = 10   | # Scroll up 10 steps.   |
        | Scroll From Pattern At Coordinates | pattern.png = 0.80 |  Down = 10 | # Scroll down 10 steps. |
        """
        self.hover_at_pattern_at_coordinates(pattern, xoffset, yoffset)
        self._info("Scrolling '%s' in pattern '%s'  at coordinates '%s', '%s'." % (scroll, pattern, xoffset, yoffset))
        self._scroll_direction_and_steps_from_pattern(pattern, scroll, xoffset, yoffset)

    def scroll_x_steps(self, scroll):
        """Scroll up or down as specified by the `scroll` step.

        This keyword must be paired with `Hover At Pattern` in order to execute scrolling action within the region.
        Examples:
        | Hover At Pattern | pattern.png | # Hover at element identified by pattern.png |
        | Scroll X Steps   | Up = 10     | # Scroll up 10 steps.                        |
        | Scroll X Steps   | Down = 10   | # Scroll down 10 steps.                      |
        """
        self._info("Scrolling '%s'." % (scroll))
        self._scroll_direction_and_steps(scroll)

    """************************** MOUSE ACTIONS DRAG AND DROP *****************************"""

    def drag_pattern(self, pattern):
        """`Drag Pattern` and `Drop At Pattern` keywords must be used in pairs to complete a drag and drop action.

        Examples:
        | Drag Pattern    | pattern.png = 0.90 | # Drag element identified by pattern.png    |
        | Drop At Pattern | pattern.png = 0.90 | # Drag at element identified by pattern.png |
        """
        self._info("Dragging element '%s'." % pattern)
        drag(self._pattern_find(pattern, None, None))

    def drop_at_pattern(self, pattern):
        """`Drag Pattern` and `Drop At Pattern` keywords must be used in pairs to complete a drag and drop action.

        Examples:
        | Drag Pattern    | pattern.png | # Drag element identified by pattern.png    |
        | Drop At Pattern | pattern.png | # Drag at element identified by pattern.png |
        """
        self._info("Dropping at element '%s'." % pattern)
        dropAt(self._pattern_find(pattern, None, None))

    def drag_pattern_in_coordinates(self, pattern, xoffset, yoffset):
        """Drag element at `x/y` coordinates of the element identified by ``pattern``.
        """
        self._info("Dragging element '%s' in coordinates '%s', '%s'." % (pattern, xoffset, yoffset))
        drag(self._pattern_find(pattern, xoffset, yoffset))

    def drop_pattern_at_coordinates(self, pattern, xoffset, yoffset):
        """Drop or release mouse button element at `x/y` coordinates of the element identified by ``pattern``.
        """
        self._info("Dropping element '%s' in coordinates '%s', '%s'." % (pattern, xoffset, yoffset))
        dropAt(self._pattern_find(pattern, xoffset, yoffset))

    def drag_and_drop_element(self, pattern1, pattern2):
        """Drag and drop an element identified by ``pattern1`` to another element identified by ``pattern2``.

        Example:
        | Drag and drop | pattern1.png = 0.90 | pattern2.png = 0.90 | # Drag element identified by pattern.png |
        """
        self._info("Performing drag and drop from element '%s' to element '%s'." % (pattern1, pattern2))
        dragDrop(self._pattern_find(pattern1, None, None), self._pattern_find(pattern2, None, None))

    """***************************** KEYBOARD ACTIONS ************************************"""

    def paste_text_in_pattern(self, pattern, text):
        """Paste a `text` in element identified by ``pattern``.

        Example:
        | Paste Text In Pattern | pattern.png = 0.90 | This is a sample text. | # Paste a text in element identified by pattern.png |
        """
        text = str(text)
        self._info("Pasting text '%s' in pattern '%s'." % (text, pattern))
        self._pattern_find(pattern, None, None).paste(text)

    def paste_text_in_pattern_at_coordinates(self, pattern, text, xoffset, yoffset):

        """Paste a `text` at `x/y` coordinates of the element identified by ``pattern``.
        Example:
        | Paste Text In Pattern | pattern.png = 0.90 | 30 | 30 | This is a sample text. | # Paste a text in x/y coordinates of element identified by pattern.png |
        """
        self._info("Pasting text '%s' in '%s'  at coordinates '%s', '%s'." % (text, pattern, xoffset, yoffset))
        self._pattern_find(pattern, xoffset, yoffset).paste(text)

    def type_text_in_pattern(self, pattern, text):
        """Type a `text` in element identified by ``pattern``.

        Example:
        | Type Text In Pattern | pattern.png = 0.90 | This is a sample text. | # Type a text in element identified by pattern.png |
        """
        text = str(text)
        self._info("Typing '%s' in pattern '%s'." % (text, pattern))
        self._pattern_find(pattern, None, None).type(text)

    def type_text_in_pattern_at_coordinates(self, pattern, text, xoffset, yoffset):
        """Type a `text` at `x/y` coordinates of the element identified by ``pattern``.

        Example:
        | Type Text In Pattern | pattern.png = 0.90 | 30 | 30 | This is a sample text. | # Type a text in x/y coordinates of element identified by pattern.png |
        """
        self._info("Typing text '%s' in '%s'  at coordinates '%s', '%s'." % (text, pattern, xoffset, yoffset))
        self._pattern_find(pattern, xoffset, yoffset).type(text)

    """***************************** READ TEXTS IN PATTERN ************************************
    Note: OCR tessdata should downloaded then put in a local directory
    For Windows, it should be put inside C:\Users\<user>\AppData\Roaming\Sikulix\SikulixTesseract
    Or: User must select the last two options in the SikuliX installation to install both the script and tesseract.
    """

    def get_text_in_pattern(self, pattern, search_location):
        """Returns the text in an ``area`` at a ``spatial location`` in reference to an element identified by ``pattern``

        Examples:
        | Get Text In Pattern | pattern.png | None        | # Returns the text within 300px left of element identified by pattern.png  |
        | Get Text In Pattern | pattern.png | left = 300  | # Returns the text within 300px left of element identified by pattern.png  |
        | Get Text In Pattern | pattern.png | right = 400 | # Returns the text within 400px right of element identified by pattern.png |
        | Get Text In Pattern | pattern.png | above = 500 | # Returns the text within 500px above of element identified by pattern.png |
        | Get Text In Pattern | pattern.png | below = 600 | # Returns the text within 600px below of element identified by pattern.png |
        """
        self._info("Getting texts in pattern at '%s' of pattern '%s'." % (search_location, pattern))
        return self._read_text_in_pattern(pattern, search_location)

    def get_text_in_search_region(self, search_location):
        """Returns the text from a specified ``search location``. 

        This keyword must be paired with any of the following keywords:
        `Set Search Region To Target Screen`, `Set New Search Region In Active App`, 
        `Set Search Region To Application`, `Set New Search Region In Target Screen` or 
        `Set New Search Region In Application`.

        See also `Click Region`, `Double Click Region`, `Right Click Region`,
        and `Highlight Region`.

        Examples:
        | Set New Search Region In Active App | 10, 60, -20, -270 | # Sets offset values to a region of active app.        |
        | Get Text In Search Region           | region            | # Returns the text within the specified search region. |
        | Get Text In Search Region           | left 300          | # Returns the text within the specified search region. |
        | Get Text In Search Region           | right 400         | # Returns the text within the specified search region. |
        | Get Text In Search Region           | above 500         | # Returns the text within the specified search region. |
        """
        self._info("Getting texts from at '%s' of specified ROI." % (search_location))
        return self._read_text_in_region(search_location)

    """***************************** DO SOMETHING IN MATCHING PATTERNS IN ACTIVE WINDOW ************************************
    Keywords used when multiple patterns on screen is present.
    Search region or setROI() value is set to the application in focus as default.
    Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
    """

    def get_pattern_count_in_active_app(self, pattern):
        """Returns the count of elements identified by ``pattern`` in the region of an active application.

        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.
        """
        self._info("Getting count of pattern '%s' in active app." % pattern)
        return len(self._get_all_patterns_in_active_app(pattern))

    def click_nth_pattern_in_active_app(self, pattern, pattern_index):
        """Perform a mouse ``click`` on the click point using the ``left`` button.

        Click point is at the `center` of the nth element identified by ``pattern``.
        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at maximum level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Example:
        | Click Nth Pattern In Active App | pattern.png = 0.99 | 3 | # Clicks the third instance of an element identified by pattern.png |
        """
        self._info("Clicking '%s'nth pattern '%s' in active app." % (pattern_index, pattern))
        self._get_nth_pattern(pattern, pattern_index).click()

    def right_click_nth_pattern_in_active_app(self, pattern, pattern_index):
        """Perform a mouse ``click`` on the click point using the ``right`` button.

        Click point is at the `center` of the nth element identified by ``pattern``.
        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Example:
        | Right Click Nth Pattern In Active App | pattern.png = 0.99 | 4 | # Right-clicks the fourth instance of an element identified by pattern.png |
        """
        self._info("Clicking '%s'nth pattern '%s' in active app." % (pattern_index, pattern))
        self._get_nth_pattern(pattern, pattern_index).rightClick()

    def double_click_nth_pattern_in_active_app(self, pattern, pattern_index):
        """Perform a mouse ``double-click`` on the click point using the ``left`` button.

        Click point is at the `center` of the nth element identified by ``pattern``.
        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Example:
        | Double Click Nth Pattern In Active App | pattern.png = 0.99 | 5 | # Double-clicks the fifth instance of an element identified by pattern.png |
        """

        self._info("Double-clicking '%s'nth pattern '%s' in active app." % (pattern_index, pattern))
        self._get_nth_pattern(pattern, pattern_index).doubleClick()

    def hover_at_nth_pattern_in_active_app(self, pattern, pattern_index):
        """Hovers mouse pointer at the center the nth element identified by ``pattern``.

        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Example:
        | Hover At Nth Pattern In Active App | pattern.png = 0.99 | 7 | # Hovers mouse pointer the seventh instance of an element identified by pattern.png |
        """

        self._info("Hovering at '%s'nth pattern '%s' in active app." % (pattern_index, pattern))
        self._get_nth_pattern(pattern, pattern_index).hover()

    def highlight_nth_pattern_in_active_app(self, pattern, pattern_index, highlight_duration):
        """Highlights the nth element identified by ``pattern`` for a specified `highlight_duration` in seconds.

        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Example:
        | Highlight Nth Pattern In Active App | pattern.png = 0.99 | 6   | 2   | 
        # Highlights the sixth instance of an element identified by pattern.png for 2 seconds.
       
        """

        self._info(
            "Highlighting '%s'nth pattern '%s' in active app for '%s' second(s)."
            % (pattern_index, pattern, highlight_duration)
        )
        self._get_nth_pattern(pattern, pattern_index).highlight(highlight_duration)

    def drag_nth_pattern_in_active_app(self, pattern, pattern_index):
        """Drag the nth element identified by ``pattern``.
        `Drag Nth Pattern In Active App` and `Drop At Nth Pattern In Active App` keywords must be used in pairs to complete a drag and drop action.

        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Examples:
        | Drag Nth Pattern In Active App    | pattern.png = 0.99 | 1  | # Drags the first instance of an element identified by pattern.png   |
        | Drop At Nth Pattern In Active App | pattern.png = 0.99 | 13 | # Drops at the 13th instance of an element identified by pattern.png |
        """

        self._info("Dragging '%s'nth pattern '%s' in active app." % (pattern_index, pattern))
        drag(self._get_nth_pattern(pattern, pattern_index))

    def drop_at_nth_pattern_in_active_app(self, pattern, pattern_index):
        """Drop at the nth element identified by ``pattern``.
        `Drag Nth Pattern In Active App` and `Drop At Nth Pattern In Active App` keywords must be used in pairs to complete a drag and drop action.

        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Examples:
        | Drag Nth Pattern In Active App    | pattern.png = 0.99 | 13  | # Drags the 13th instance of an element identified by pattern.png   |
        | Drop At Nth Pattern In Active App | pattern.png = 0.99 | 1 | # Drops at the first instance of an element identified by pattern.png |
        """

        self._info("Dropping at '%s'nth pattern '%s' in active app." % (pattern_index, pattern))
        dropAt(self._get_nth_pattern(pattern, pattern_index))

    def drag_and_drop_from_nth_pattern(self, pattern1, pattern1_index, pattern2, pattern2_index):
        """Drag and drop an nth element identified by ``pattern1`` to another nth element identified by ``pattern2``.

        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Examples:
        | Drag and drop | pattern1.png = 0.90 | 1 | pattern2.png = 0.90 | 2 | # Drag and drop the first instance of pattern1.png to the 2nd instance of pattern2.png |
        | Drag and drop | pattern.png = 0.90  | 3 | pattern.png = 0.90  | 4 | # Drag and drop the third instance to the fourth instance of pattern.png |
        """

        self._info("Performing drag and drop from element '%s' to element '%s'." % (pattern1, pattern2))
        dragDrop(self._get_nth_pattern(pattern1, pattern1_index), self._get_nth_pattern(pattern2, pattern2_index))

    def paste_text_in_nth_pattern_in_active_app(self, pattern, pattern_index, text):
        """Paste a `text` at `x/y` coordinates of the element identified by ``pattern``.

        Example:
        | Type Text In Pattern | pattern.png = 0.90 | This is a sample text. | # Type a text in element identified by pattern.png |
        """

        self._info("Pasting text '%s' in '%s'nth pattern '%s' in active app." % (text, pattern_index, pattern))
        self._get_nth_pattern(pattern, pattern_index).type(text)

    def type_text_in_nth_pattern_in_active_app(self, pattern, pattern_index, text):
        """Type a `text` in nth element identified by ``pattern``.

        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Example:
        | Type Text At Nth Pattern In Active App | pattern.png = 0.90 | 3 | This is a sample text. | # Type a text in third element identified by pattern.png |
        """

        self._info("Typing text '%s' in '%s'nth pattern '%s' in active app." % (text, pattern_index, pattern))
        self._get_nth_pattern(pattern, pattern_index).type(text)

    def get_text_in_nth_pattern(self, pattern, pattern_index, search_location):
        """Return the `text` in nth element identified by ``pattern``.

        This Keyword is useful when multiple patterns on screen is present.
        Search region or setROI() value is set to the application in focus as default.
        Pattern sensitivity must be set at max level (0.99) in order to avoid false positives during image detections.
        Search for matching patterns is set to top > down > left > right.

        Examples:
        | Get Text In Nth Pattern At Location And Area | pattern.png | 1 | None        | # Returns the text of the first instance of pattern.png                     |
        | Get Text In Nth Pattern At Location And Area | pattern.png | 1 | left = 300  | # Returns the text within 300px left of the first instance of pattern.png   |
        | Get Text In Nth Pattern At Location And Area | pattern.png | 2 | right = 400 | # Returns the text within 400px right of the second instance of pattern.png |
        | Get Text In Nth Pattern At Location And Area | pattern.png | 3 | above = 500 | # Returns the text within 500px above of the third instance of pattern.png  |
        | Get Text In Nth Pattern At Location And Area | pattern.png | 5 | below = 600 | # Returns the text within 600px below of the fifth instance of pattern.png  |
        """

        self._info(
            "Getting texts in '%s' nth pattern at '%s' of pattern '%s'." % (pattern_index, search_location, pattern)
        )
        pattern = self._get_nth_pattern(pattern, pattern_index)
        return self._read_text(pattern, search_location)

    # Private
    """***************************** Internal methods ************************************"""

    def _pattern_find(self, pattern, xoffset, yoffset):
        """Finds ``pattern`` on search region set by active application.
        To do: dynamic search region where user can set the search region to either, active application, specific region or screen
        """

        active_app_window = App.focusedWindow()
        app_coordinates = (
            active_app_window.getX(),
            active_app_window.getY(),
            active_app_window.getW(),
            active_app_window.getH(),
        )
        setROI(*app_coordinates)
        matching_pattern = self._pattern_finder._find_pattern(pattern)
        try:
            if xoffset != None or yoffset != None:
                xoffset = int(xoffset)
                yoffset = int(yoffset)
                element = active_app_window.find(matching_pattern.targetOffset(xoffset, yoffset))
            else:
                element = active_app_window.find(matching_pattern)
            return element
        except FindFailed, err:
            raise AssertionError("No matching pattern: %s found on screen." % (pattern))
 def __init__(self):
     # Set target coordinates to Screen 1 as default
     self.target_screen = None
     self._pattern_finder = PatternFinder()
class _RegionKeywords(KeywordGroup):
    def __init__(self):
        # Set target coordinates to Screen 1 as default
        self.target_screen = None
        self._pattern_finder = PatternFinder()

    # Public

    def set_search_region_to_target_screen(self, target_screen):
        """Sets the ROI or the search area to a specified ``target_screen``.
        Searching for pattern match is faster if the search region is smaller.

        For more information on multi-monitor environment, see https://sikulix-2014.readthedocs.org/en/latest/screen.html

        See also `Set Search Region To Active App`, `Set New Search Region In Active App`, `Set Search Region To Application`
        `Set New Search Region In Target Screen`, and `Set New Search Region In Application`.

        Example:
        | Set Search Region To Target Screen | Screen 0 | # Sets ROI to the Primary Monitor  |
        | Set Search Region To Target Screen | Screen 1 | # Sets ROI to Additional Monitor 1 |
        | Set Search Region To Target Screen | Screen 2 | # Sets ROI to Additional Monitor 2 |
        | Set Search Region To Target Screen | Screen 3 | # Sets ROI to Additional Monitor 3 |

        """
        self._info("Setting search region to '%s'." % target_screen)
        self.target_screen = target_screen
        screen_number = self._parse_target_screen(self.target_screen)
        setROI(Region(Screen(screen_number)))
        #setRect(Region(Screen(screen_number)))

    def set_search_region_to_active_app(self):
        """Sets the ROI or the search area to the application in focus.
        Searching for pattern match is faster if the search region is smaller.

        Example:
        | Set Search Region To Active App | # Sets the search region to the application in focus | 

        See also `Set Search Region To Target Screen`, `Set New Search Region In Active App`, `Set Search Region To Application`,
        `Set New Search Region In Target Screen` and `Set New Search Region In Application`.
        """
        self._info("Setting the search region to the active application.")
        search_region = self.get_active_app_region()
        self._info("Setting the search region to '%s'." % (search_region))
        setROI(search_region)
        #setRect(search_region)

    def set_search_region_to_application(self, app_name):
        """Sets the ROI or the search area to the application as specified in `app_name`.
        Searching for pattern match is faster if the search region is smaller.

        Example:
        | Set Search Region To Application | Calculator | # Sets the search region to the Calculator application. | 

        See also `Set Search Region To Target Screen`, `Set New Search Region In Active App`,
        `Set New Search Region In Target Screen` and `Set New Search Region In Application`.
        """
        search_region = App(app_name).window()
        self._info("Setting the search region: '%s' to the application: '%s'." % (app_name, search_region))
        setROI(search_region)
        #setRect(search_region)

    def set_new_search_region_in_active_app(self, offsets):
        """Sets new ROI or the search area to a specified ``offsets`` based on original coordinate values of active application in focus.

        See also `Set Search Region To Target Screen`, `Set Search Region To Active App`, `Set Search Region To Application`,
        `Set New Search Region In Target Screen`.

        Example:
        | Set New Search Region In Active App | 10, 60, -20, -270 | 
        # Offsets x, y, height, width to 10, 60, -20, -270 pixels respectively.
        """
        self._info("Setting new search region to offsets '%s'." % offsets)
        (offsetx, offsety, offsetw, offseth) = self._parse_coordinate_offsets(offsets)
        active_app_region = self.get_active_app_region()
        self._info("Active app region '%s'." % active_app_region)
        new_x = active_app_region.x + offsetx
        new_y = active_app_region.y + offsety
        new_w = active_app_region.w + offsetw
        new_h = active_app_region.h + offseth
        new_coordinates = (new_x, new_y, new_w, new_h)
        
        self._info("New coordinates: x:'%s' y:'%s w:'%s h:'%s." % new_coordinates)
        setROI(*new_coordinates)
        #setRect(*new_coordinates)

    def set_new_search_region_in_application(self, app_name, offsets):
        """Sets new ROI or the search area to a specified ``offsets`` based on original coordinate values of application as specified in `app_name`.

        See also `Set Search Region To Target Screen`, `Set Search Region To Active App`, `Set Search Region To Application`,
        and `Set New Search Region In Target Screen`.

        Example:
        | Set New Search Region In Application | Calculator | 10, 60, -20, -270 | 
        # Offsets x, y, height, width to 10, 60, -20, -270 pixels respectively.
        """
        self._info("Setting new search region to offsets '%s'." % offsets)
        (offsetx, offsety, offsetw, offseth) = self._parse_coordinate_offsets(offsets)
        application_region = self.get_application_region(app_name)
        self._info("Application region '%s'." % application_region)
        new_x = application_region.x + offsetx
        new_y = application_region.y + offsety
        new_w = application_region.w + offsetw
        new_h = application_region.h + offseth
        new_coordinates = (new_x, new_y, new_w, new_h)
        
        self._info("New coordinates: x:'%s' y:'%s w:'%s h:'%s." % new_coordinates)

        setROI(*new_coordinates)
        #setRect(*new_coordinates)

    def set_new_search_region_in_target_screen(self, offsets, target_screen):
        """Sets new ROI or new search area to a specified ``offsets`` based on original coordinate values of `target screen`.

        See also `Set Search Region To Target Screen`, `Set New Search Region In Active App`, `Set Search Region To Application`,
        `Set Search Region To Active App` and `Set New Search Region In Application`.

        Example:
        | Set New Search Region In Target Screen | 10, 60, -20, -270 | Screen 0 |
        # Offsets x, y, height, width of the Primary Monitor to 10, 60, -20, -270 pixels respectively.
        """
        self._info("Setting new search region to offsets '%s' of '%s'." % (offsets, target_screen))
        self.target_screen = target_screen
        (offsetx, offsety, offsetw, offseth) = self._parse_coordinate_offsets(offsets)
        screen_number = self._parse_target_screen(self.target_screen)
        self._info("'%s' region '%s'." % (target_screen, screen_number))

        new_x = Sceen(screen_number).x + offsetx
        new_y = Sceen(screen_number).y + offsety
        new_w = Sceen(screen_number).w + offsetw
        new_h = Sceen(screen_number).h + offseth
        new_coordinates = (new_x, new_y, new_w, new_h)
        
        self._info("New coordinates: x:'%s' y:'%s w:'%s h:'%s." % new_coordinates)
        setROI(*new_coordinates)
        #setRect(*new_coordinates)

    def get_active_screen_coordinates(self, target_screen):
        """Returns the ``coordinates`` of the screen as specified in `target_screen`.
        """
        screen_number = self._parse_target_screen(target_screen)
        coordinates = (Screen(screen_number).getX(), 
                       Screen(screen_number).getY(), 
                       Screen(screen_number).getW(), 
                       Screen(screen_number).getH())
        return coordinates

    def get_active_app_coordinates(self):
        """Returns the ``coordinates`` of the `application` in focus.
        Keyword must be combined with `Set Application Focus`.

        Examples:
        | Set Application Focus      | My Awesome App | # Sets the focus to `My Awesome App`      |
        | Get Active App Coordinates |                |# Gets the coordinates of `My Awesome App` |
        """
        activeWindow = App.focusedWindow()
        coordinates = (activeWindow.getX(), 
                       activeWindow.getY(), 
                       activeWindow.getW(), 
                       activeWindow.getH())
        return coordinates

    def get_application_coordinates(self, app_name):
        """Returns the ``coordinates`` of the `application` in focus.

        Examples:
        | Set Application Focus      | My Awesome App | # Sets the focus to `My Awesome App`      |
        | Get Active App Coordinates |                |# Gets the coordinates of `My Awesome App` |
        """
        applicationWindow = App(app_name).window()
        coordinates = (applicationWindow.getX(), 
                       applicationWindow.getY(), 
                       applicationWindow.getW(), 
                       applicationWindow.getH())
        return coordinates

    def get_application_xywh_coordinate(self, app_name, coordinate):
        """Returns the ``xy coordinate`` or the ``width`` or ``height`` of the `application` as specified in `app_name`.
        """
        self._info("Getting'%s' value for application '%s." % (coordinate, app_name))
        assert coordinate is not None and len(coordinate) > 0
        applicationWindow = App(app_name).window()
        if (coordinate == x):
            return applicationWindow.x
        elif (coordinate == y):
            return applicationWindow.y
        elif (coordinate == w):
            return applicationWindow.w
        elif (coordinate == h):
            return applicationWindow.h
        else:
            raise ValueError("Invalid value for coordinate type, input value is: '%s'" % (coordinate))

    def get_active_app_xywh_coordinate(self, coordinate):
        """Returns the ``xy coordinate`` or the ``width`` or ``height`` of the active application in focus.
        """
        self._info("Getting'%s' value for application '%s." % (coordinate, app_name))
        assert coordinate is not None and len(coordinate) > 0
        activeWindow = App.focusedWindow()
        if (coordinate == x):
            return activeWindow.x
        elif (coordinate == y):
            return activeWindow.y
        elif (coordinate == w):
            return activeWindow.w
        elif (coordinate == h):
            return activeWindow.h
        else:
            raise ValueError("Invalid value for coordinate type, input value is: '%s'" % (coordinate))

    def get_reference_pattern_coordinates(self, pattern):
        """Returns the ``coordinates`` of the element identified by ``pattern``.

        Example:
        | Get Reference Pattern Coordinates | pattern.png = 0.90 | # Gets the coordinates of pattern.png |
        """
        try:
            matched_pattern = find(self._pattern_finder._find_pattern(pattern))
            coordinates = (matched_pattern.getX(), matched_pattern.getY(), matched_pattern.getW(), matched_pattern.getH())
            return coordinates
        except FindFailed, err:
            raise AssertionError("Unable to find matching pattern '%s'." % (pattern))