# Licensed to the Software Freedom Conservancy (SFC) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The SFC licenses this file
# to you 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.

from hashlib import md5 as md5_hash

from .command import Command
from ..common.by import By


class ShadowRoot():

    # TODO: We should look and see  how we can create a search context like Java/.NET

    def __init__(self, session, id_):
        self.session = session
        self._id = id_

    def __eq__(self, other_shadowroot):
        return self._id == other_shadowroot._id

    def __hash__(self):
        return int(md5_hash(self._id.encode('utf-8')).hexdigest(), 16)

    def __ne__(self, other_shadowroot):
        return not self.__eq__(other_shadowroot)

    def __repr__(self):
        return '<{0.__module__}.{0.__name__} (session="{1}", element="{2}")>'.format(
            type(self), self.session.session_id, self._id)

    def find_element(self, by=By.ID, value=None):
        return self._execute(Command.FIND_ELEMENT_FROM_SHADOW_ROOT, {"using": by, "value": value})['value']

    def find_elements(self, by=By.ID, value=None):
        return self._execute(Command.FIND_ELEMENTS_FROM_SHADOW_ROOT, {"using": by, "value": value})['value']

    # Private Methods
    def _execute(self, command, params=None):
        """Executes a command against the underlying HTML element.

        Args:
          command: The name of the command to _execute as a string.
          params: A dictionary of named parameters to send with the command.

        Returns:
          The command's JSON response loaded into a dictionary object.
        """
        if not params:
            params = {}
        params['shadowId'] = self._id
        return self.session.execute(command, params)

@@ -892,18 +892,16 @@
 adowRoot
-()
 :%0A%0A    #
@@ -1236,15 +1236,15 @@
 ode(
-'
+%22
 utf-8
-'
+%22
 )).h
@@ -1517,16 +1517,25 @@
 self._id
+%0A        
 )%0A%0A    d
@@ -1550,33 +1550,39 @@
 element(self, by
-=
+: By = 
 By.ID, value=Non
@@ -1569,33 +1569,40 @@
 y = By.ID, value
-=
+: str = 
 None):%0A        r
@@ -1613,32 +1613,45 @@
 n self._execute(
+%0A            
 Command.FIND_ELE
@@ -1698,33 +1698,42 @@
 lue%22: value%7D
+%0A        
 )%5B
-'
+%22
 value
-'
+%22
 %5D%0A%0A    def f
@@ -1753,17 +1753,23 @@
 self, by
-=
+: By = 
 By.ID, v
@@ -1772,17 +1772,24 @@
 D, value
-=
+: str = 
 None):%0A 
@@ -1816,16 +1816,29 @@
 execute(
+%0A            
 Command.
@@ -1902,17 +1902,26 @@
 lue%7D
+%0A        
 )%5B
-'
+%22
 value
-'
+%22
 %5D%0A%0A 
@@ -2381,17 +2381,17 @@
 ams%5B
-'
+%22
 shadowId
 '%5D =
@@ -2386,17 +2386,17 @@
 shadowId
-'
+%22
 %5D = self

Add type hinting to Shadowroot