# Copyright 2008-2013 Software freedom conservancy
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.


"""WebElement implementation."""
import hashlib
import os
import zipfile
try:
    from StringIO import StringIO as IOStream
except ImportError:  # 3+
    from io import BytesIO as IOStream
import base64


from .command import Command
from selenium.common.exceptions import WebDriverException
from selenium.common.exceptions import InvalidSelectorException
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys

try:
    str = basestring
except NameError:
    pass


class WebElement(object):
    """Represents an HTML element.

    Generally, all interesting operations to do with interacting with 
a page
    will be performed through this interface."""
    def __init__(self, parent, id_):
        self._parent = parent
        self._id = id_

    @property
    def tag_name(self):
        """Gets this element's tagName property."""
        return self._execute(Command.GET_ELEMENT_TAG_NAME)['value']

    @property
    def text(self):
        """Gets the text of the element."""
        return self._execute(Command.GET_ELEMENT_TEXT)['value']

    def click(self):
        
"""Clicks the element."""
        self._execute(Command.CLICK_ELEMENT)

    def submit(self):
        """Submits a form."""
        self._execute(Command.SUBMIT_ELEMENT)

    def clear(self):
        """Clears the text if it's a text entry element."""
        self._execute(Command.CLEAR_ELEMENT)

    def get_attribute(self, name):
        """Gets the attribute value.

        :Args:
            - name - name of the attribute property to retieve.

        Example::

            # Check if the 'active' css class is applied to an element.
            is_active = "active" in target_element.get_attribute("class")

        """
        resp = self._execute(Command.GET_ELEMENT_ATTRIBUTE, {'name': name})
        attributeValue = ''
        if resp['value'] is None:
            attributeValue = None
        else:
            attributeValue = resp['value']
            if name != 'value' and attributeValue.lower() in ('true', 'false'):
                attributeValue = attributeValue.lower()

        return attributeValue

    def is_selected(self):
        """Whether the element is selected.

        Can be used to check if a checkbox or radio button is selected.
        """
        return self._execute(Command.IS_ELEMENT_SELECTED)['value']

    def is_enabled(self):
        """Whether the element is enabled."""
        return self._execute(Command.IS_ELEMENT_ENABLED)['value']

    def find_element_by_id(self, id_):
        """Finds element within the child elements of this element.

        :Args:
            - id_ - ID of child element to locate.
        """
        return self.find_element(by=By.ID, value=id_)

    def find_elements_by_id(self, id_):
        """Finds a list of elements within the children of this element
        with the matching ID.

        :Args:
            - id_ - Id of child element to find.
        """
        return self.find_elements(by=By.ID, value=id_)

    def find_element_by_name(self, name):
        """Find element with in this element's children by name.
        :Args:
            - name - name property of the element to find.
        """
        return self.find_element(by=By.NAME, value=name)

    def find_elements_by_name(self, name):
        """Finds a list of elements with in this element's children by name.

        :Args:
            - name - name property to search for.
        """
        return self.find_elements(by=By.NAME, value=name)

    def find_element_by_link_text(self, link_text):
        """Finds element with in this element's children by visible link text.

        :Args:
            - link_text - Link text string to search for.
        """
        return self.find_element(by=By.LINK_TEXT, value=link_text)

    def find_elements_by_link_text(self, link_text):
        """Finds a list of elements with in this element's children by visible link text.

        :Args:
            - link_text - Link text string to search for.
        """
        return self.find_elements(by=By.LINK_TEXT, value=link_text)

    def find_element_by_partial_link_text(self, link_text):
        """Finds element with in this element's children by parial visible link text.

        :Args:
            - link_text - Link text string to search for.
        """
        return self.find_element(by=By.PARTIAL_LINK_TEXT, value=link_text)

    def find_elements_by_partial_link_text(self, link_text):
        """Finds a list of elements with in this element's children by link text.

        :Args:
            - link_text - Link text string to search for.
        """
        return self.find_elements(by=By.PARTIAL_LINK_TEXT, value=link_text)

    def find_element_by_tag_name(self, name):
        """Finds element with in this element's children by tag name.

        :Args:
            - name - name of html tag (eg: h1, a, span)
        """
        return self.find_element(by=By.TAG_NAME, value=name)

    def find_elements_by_tag_name(self, name):
        """Finds a list of elements with in this element's children by tag name.

        :Args:
            - name - name of html tag (eg: h1, a, span)
        """
        return self.find_elements(by=By.TAG_NAME, value=name)

    def find_element_by_xpath(self, xpath):
        """Finds element by xpath.

        :Args:
            xpath - xpath of element to locate.  "//input[@class='myelement']"

        Note: The base path will be relative to this element's location.

        This will select the first link under this element.::

            myelement.find_elements_by_xpath(".//a")

        However, this will select the first link on the page.

            myelement.find_elements_by_xpath("//a")

        """
        return self.find_element(by=By.XPATH, value=xpath)

    def find_elements_by_xpath(self, xpath):
        """Finds elements within the elements by xpath.

        :Args:
            - xpath - xpath locator string.

        Note: The base path will be relative to this element's location.

        This will select all links under this element.::

            myelement.find_elements_by_xpath(".//a")

        However, this will select all links in the page itself.

            myelement.find_elements_by_xpath("//a")
        """
        return self.find_elements(by=By.XPATH, value=xpath)

    def find_element_by_class_name(self, name):
        """Finds an element within this element's children by their class name.

        :Args:
            - name - class name to search on.
        """
        return self.find_element(by=By.CLASS_NAME, value=name)

    def find_elements_by_class_name(self, name):
        """Finds a list of elements within children of this element by their class name.

        :Args:
            - name - class name to search on.
        """
        return self.find_elements(by=By.CLASS_NAME, value=name)

    def find_element_by_css_selector(self, css_selector):
        """Find and return an element that's a child of this element by CSS selector.

        :Args:
            - css_selector - CSS selctor string, ex: 'a.nav#home'
        """
        return self.find_element(by=By.CSS_SELECTOR, value=css_selector)

    def find_elements_by_css_selector(self, css_selector):
        """Find and return list of multiple elements within the children of this
        element by CSS selector.

        :Args:
            - css_selector - CSS selctor string, ex: 'a.nav#home'
        """
        return self.find_elements(by=By.CSS_SELECTOR, value=css_selector)

    def send_keys(self, *value)