require 'watir-webdriver/extensions/alerts'
require 'page-object/elements'
require 'page-object/core_ext/string'


module PageObject
  module Platforms
    module WatirWebDriver
      #
      # Watir implementation of the page object platform driver.  You should not use the
      # class directly.  Instead you should include the PageObject module in your page object
      # and use the methods dynamically added from the PageObject::Accessors module.
      #
      class PageObject
        attr_reader :browser

        def initialize(browser)
          @browser = browser
        end

        #
        # platform method to navigate to a provided url
        # See PageObject#navigate_to
        #
        def navigate_to(url)
          @browser.goto url
        end
        
        #
        # platform method to get the current url
        # See PageObject#current_url
        #
        def current_url
          @browser.url
        end

        #
        # platform method to retrieve the text from the current page
        # See PageObject#text
        #
        def text
          @browser.text
        end

        #
        # platform method to retrieve the html for the current page
        # See PageObject#html
        #
        def html
          @browser.html
        end

        #
        # platform method to retrieve the title for the current page
        # See PageObject#title
        #
        def title
          @browser.title
        end

        #
        # platform method to wait for a block to return true
        # See PageObject#wait_until
        def wait_until(timeout, message = nil, &block)
          @browser.wait_until(timeout, message, &block)
        end

        #
        # platform method to handle an alert popup
        # See PageObject#alert
        #
        def alert(frame=nil, &block)
          switch_to_frame(frame)
          yield
          value = nil
          if @browser.alert.exists?
            value = @browser.alert.text
            @browser.alert.ok
          end
          switch_to_default_content(frame)
          value
        end

        #
        # platform method to handle a confirm popup
        # See PageObject#confirm
        #
        def confirm(response, frame=nil, &block)
          switch_to_frame(frame)
          yield
          value = nil
          if @browser.alert.exists?
            value = @browser.alert.text
            response ? @browser.alert.ok : @browser.alert.close
          end
          switch_to_default_content(frame)
          value
        end

        #
        # platform method to handle a prompt popup
        # See PageObject#prompt
        #
        def prompt(answer, frame=nil, &block)
          switch_to_frame(frame)
          @browser.wd.execute_script "window.prompt = function(text, value) { window.__lastWatirPrompt = { message: text, default_value: value }; return #{answer}; }"
          yield
          result = @browser.wd.execute_script "return window.__lastWatirPrompt"
          switch_to_default_content(frame)
          result && result.dup.each_key { |k| result[k.to_sym] = result.delete(k) }
          result
        end

        #
        # platform method to execute javascript on the browser
        # See PageObject#execute_script
        #
        def execute_script(script)
          @browser.execute_script(script)
        end
    
        #
        # platform method to handle attaching to a running window
        # See PageObject#attach_to_window
        #
        def attach_to_window(identifier, &block)
          win_id = {identifier.keys.first => /#{Regexp.escape(identifier.values.first)}/}
          @browser.window(win_id).use &block
        end

        def element_with_focus
          element = browser.execute_script("return document.activeElement")
          type = element.type.to_sym if element.tag_name.to_sym == :input
          cls = ::PageObject::Elements.element_class_for(element.tag_name, type)
          cls.new(element, :platform => :watir_webdriver)    
        end

        #
        # platform method to switch to a frame and execute a block
        # See PageObject#in_frame
        #
        def in_frame(identifier, frame=nil, &block)
          frame = [] if frame.nil?
          frame << identifier
          block.call(frame)
        end
    
        #
        # platform method to refresh the page
        # See PageObject#refresh
        #
        def refresh
          @browser.refresh
        end
    
        #
        # platform method to go back to the previous page
        # See PageObject#back
        #
        def back
          @browser.back
        end
    
        #
        # platform method to go forward to the next page
        # See PageObject#forward
        #
        def forward
          @browser.forward
        end
        
        #
        # platform method to clear the cookies from the browser
        # See PageObject#clear_cookies
        #
        def clear_cookies
          @browser.cookies.clear
        end

        #
        # platform method to save the current screenshot to a file
        # See PageObject#save_screenshot
        #
        def save_screenshot(file_name)
          @browser.wd.save_screenshot(file_name)
        end

        #
        # platform method to get the value stored in a text field
        # See PageObject::Accessors#text_field
        #
        def text_field_value_for(identifier)
          process_watir_call("text_field(identifier).value", Elements::TextField, identifier)
        end

        #
        # platform method to set the value for a text field
        # See PageObject::Accessors#text_field
        #
        def text_field_value_set(identifier, value)
          process_watir_call("text_field(identifier).set(value)", Elements::TextField, identifier, value)
        end
    
        #
        # platform method to retrieve a text field element
        # See PageObject::Accessors#text_field
        #
        def text_field_for(identifier)
          find_watir_element("text_field(identifier)", Elements::TextField, identifier)
        end

        #
        # platform method to retrieve an array of text field elements
        #
        def text_fields_for(identifier)
          elements = find_watir_elements("text_fields(identifier)", Elements::TextField, identifier)
          elements.select {|e| e.element.tag_name == 'input'}
        end

        #
        # platform method to get the value stored in a hidden field
        # See PageObject::Accessors#hidden_field
        #
        def hidden_field_value_for(identifier)
          process_watir_call("hidden(identifier).value", Elements::HiddenField, identifier)
        end

        #
        # platform method to retrieve a hidden field element
        # See PageObject::Accessors#hidden_field
        #
        def hidden_field_for(identifier)
          find_watir_element("hidden(identifier)", Elements::HiddenField, identifier)
        end

        #
        # platform method to retrieve an array of hidden field elements
        #
        def hidden_fields_for(identifier)
          find_watir_elements("hiddens(identifier)", Elements::HiddenField, identifier)
        end

        #
        # platform method to set text in a textarea
        # See PageObject::Accessors#text_area
        #
        def text_area_value_set(identifier, value)
          process_watir_call("textarea(identifier).set(value)", Elements::TextArea,
                             identifier, value)
        end

        #
        # platform method to get the text from a textarea
        # See PageObject::Accessors#text_area
        #
        def text_area_value_for(identifier)
          process_watir_call("textarea(identifier).value", Elements::TextArea, identifier)
        end

        #
        # platform method to get the text area element
        # See PageObject::Accessors#text_area
        #
        def text_area_for(identifier)
          find_watir_element("textarea(identifier)", Elements::TextArea, identifier)
        end

        #
        # platform method to retrieve an array of textarea elements
        #
        def text_areas_for(identifier)
          find_watir_elements("textareas(identifier)", Elements::TextArea, identifier)
        end

        #
        # platform method to get the currently selected value from a select list
        # See PageObject::Accessors#select_list
        #
        def select_list_value_for(identifier)
          process_watir_call("select_list(identifier).options.find {|o| o.selected?}.text",
                             Elements::SelectList, identifier)
        end

        #
        # platform method to select a value from a select list
        # See PageObject::Accessors#select_list
        #
        def select_list_value_set(identifier, value)
          process_watir_call("select_list(identifier).select(value)", Elements::SelectList,
                             identifier, value)
        end

        #
        # platform method to return the select list element
        # See PageObject::Accessors#select_list
        #
        def select_list_for(identifier)
          find_watir_element("select_list(identifier)", Elements::SelectList, identifier)
        end

        #
        # platform method to retrieve an array of select_list elements
        #
        def select_lists_for(identifier)
          find_watir_elements("select_lists(identifier)", Elements::SelectList, identifier)
        end

        #
        # platform method to click a link
        # See PageObject::Accessors#link
        #
        def click_link_for(identifier)
          call = call_for_watir_element(identifier, "link(identifier)")
          process_watir_call("#{call}.click if identifier", Elements::Link, identifier)
        end

        #
        # platform method to return a PageObject::Elements::Link object
        # see PageObject::Accessors#link
        #
        def link_for(identifier)
          call = call_for_watir_element(identifier, "link(identifier)")
          find_watir_element(call, Elements::Link, identifier)
        end

        #
        # platform method to retrieve an array of link elements
        #
        def links_for(identifier)
          call = call_for_watir_elements(identifier, "links(identifier)")
          find_watir_elements(call, Elements::Link, identifier)
        end

        #
        # platform method to check a checkbox
        # See PageObject::Accessors#checkbox
        #
        def check_checkbox(identifier)
          process_watir_call("checkbox(identifier).set", Elements::CheckBox, identifier)
        end

        #
        # platform method to uncheck a checkbox
        # See PageObject::Accessors#checkbox
        #
        def uncheck_checkbox(identifier)
          process_watir_call("checkbox(identifier).clear", Elements::CheckBox, identifier)
        end

        #
        # platform method to determine if a checkbox is checked
        # See PageObject::Accessors#checkbox
        #
        def checkbox_checked?(identifier)
          process_watir_call("checkbox(identifier).set?", Elements::CheckBox, identifier)
        end

        #
        # platform method to return a PageObject::Elements::CheckBox element
        # See PageObject::Accessors#checkbox
        #
        def checkbox_for(identifier)
          find_watir_element("checkbox(identifier)", Elements::CheckBox, identifier)
        end

        #
        # platform method to retrieve an array of checkbox elements
        #
        def checkboxs_for(identifier)
          find_watir_elements("checkboxes(identifier)", Elements::CheckBox, identifier)
        end

        #
        # platform method to select a radio button
        # See PageObject::Accessors#radio_button
        #
        def select_radio(identifier)
          process_watir_call("radio(identifier).set", Elements::RadioButton, identifier)
        end

        #
        # platform method to clear a radio button
        # See PageObject::Accessors#radio_button
        #
        def clear_radio(identifier)
          process_watir_call("radio(identifier).clear", Elements::RadioButton, identifier)
        end

        #
        # platform method to determine if a radio button is selected
        # See PageObject::Accessors#radio_button
        #
        def radio_selected?(identifier)
          process_watir_call("radio(identifier).set?", Elements::RadioButton, identifier)
        end

        #
        # platform method to return a PageObject::Eements::RadioButton element
        # See PageObject::Accessors#radio_button
        #
        def radio_button_for(identifier)
          find_watir_element("radio(identifier)", Elements::RadioButton, identifier)
        end

        #
        # platform method to retrieve an array of radio button elements
        #
        def radio_buttons_for(identifier)
          find_watir_elements("radios(identifier)", Elements::RadioButton, identifier)
        end

        #
        # platform method to return the text for a div
        # See PageObject::Accessors#div
        #
        def div_text_for(identifier)
          process_watir_call("div(identifier).text", Elements::Div, identifier, nil, 'div')
        end

        #
        # platform method to return a PageObject::Elements::Div element
        # See PageObject::Accessors#div
        #
        def div_for(identifier)
          find_watir_element("div(identifier)", Elements::Div, identifier, 'div')
        end

        #
        # platform method to retrieve an array of div elements
        #
        def divs_for(identifier)
          find_watir_elements("divs(identifier)", Elements::Div, identifier, 'div')
        end

        #
        # platform method to return the text for a span
        # See PageObject::Accessors#span
        #
        def span_text_for(identifier)
          process_watir_call("span(identifier).text", Elements::Span, identifier, nil, 'span')
        end

        #
        # platform method to return a PageObject::Elements::Span element
        # See PageObject::Accessors#span
        #
        def span_for(identifier)
          find_watir_element("span(identifier)", Elements::Span, identifier, 'span')
        end

        #
        # platform method to retrieve an array of span elements
        #
        def spans_for(identifier)
          find_watir_elements("spans(identifier)", Elements::Span, identifier, 'span')
        end

        #
        # platform method to click a button
        # See PageObject::Accessors#button
        #
        def click_button_for(identifier)
          call = call_for_watir_element(identifier, "button(identifier)")
          process_watir_call("#{call}.click", Elements::Button, identifier)
        end

        #
        # platform method to retrieve a button element
        # See PageObject::Accessors#button
        #
        def button_for(identifier)
          call = call_for_watir_element(identifier, "button(identifier)")
          find_watir_element(call, Elements::Button, identifier)
        end

        #
        # platform method to retrieve an array of button elements
        #
        def buttons_for(identifier)
          call = call_for_watir_elements(identifier, "buttons(identifier)")
          find_watir_elements(call, Elements::Button, identifier)
        end

        #
        # platform method to return the text for a table
        # See PageObject::Accessors#table
        #
        def table_text_for(identifier)
          process_watir_call("table(identifier).text", Elements::Table, identifier, nil, 'table')
        end

        #
        # platform method to retrieve a table element
        # See PageObject::Accessors#table
        #
        def table_for(identifier)
          find_watir_element("table(identifier)", Elements::Table, identifier, 'table')
        end

        #
        # platform method to retrieve an array of table elements
        #
        def tables_for(identifier)
          find_watir_elements("tables(identifier)", Elements::Table, identifier, 'table')
        end

        #
        # platform method to retrieve the text from a table cell
        # See PageObject::Accessors#cell
        #
        def cell_text_for(identifier)
          process_watir_call("td(identifier).text", Elements::TableCell, identifier,
                             nil, 'td')
        end

        #
        # platform method to retrieve a table cell element
        # See PageObject::Accessors#cell
        #
        def cell_for(identifier)
          find_watir_element("td(identifier)", Elements::TableCell, identifier, 'td')
        end

        #
        # platform method to retrieve an array of table cell elements
        #
        def cells_for(identifier)
          find_watir_elements("tds(identifier)", Elements::TableCell, identifier, 'td')
        end

        #
        # platform method to retrieve an image element
        # See PageObject::Accessors#image
        #
        def image_for(identifier)
          find_watir_element("image(identifier)", Elements::Image, identifier)
        end

        #
        # platform method to retrieve an array of image elements
        #
        def images_for(identifier)
          find_watir_elements("images(identifier)", Elements::Image, identifier)
        end

        #
        # platform method to retrieve a form element
        # See PageObject::Accessors#form
        #
        def form_for(identifier)
          find_watir_element("form(identifier)", Elements::Form, identifier)
        end

        #
        # platform method to retrieve an array of forms
        #
        def forms_for(identifier)
          find_watir_elements("forms(identifier)", Elements::Form, identifier)
        end

        #
        # platform method to retrieve the text from a list item
        # See PageObject::Accessors#list_item
        #
        def list_item_text_for(identifier)
          process_watir_call("li(identifier).text", Elements::ListItem, identifier, nil, 'li')
        end

        #
        # platform method to retrieve a list item element
        # See PageObject::Accessors#list_item
        #
        def list_item_for(identifier)
          find_watir_element("li(identifier)", Elements::ListItem, identifier, 'li')
        end

        #
        # platform method to retrieve an array of list items
        #
        def list_items_for(identifier)
          find_watir_elements("lis(identifier)", Elements::ListItem, identifier, 'li')
        end

        #
        # platform method to retrieve the text from an unordered list
        # See PageObject::Accessors#unordered_list
        #
        def unordered_list_text_for(identifier)
          process_watir_call("ul(identifier).text", Elements::UnorderedList, identifier, nil, 'ul')
        end

        #
        # platform method to retrieve an unordered list element
        # See PageObject::Accessors#unordered_list
        #
        def unordered_list_for(identifier)
          find_watir_element("ul(identifier)", Elements::UnorderedList, identifier, 'ul')
        end

        #
        # platform method to retrieve an array of unordered lists
        #
        def unordered_lists_for(identifier)
          find_watir_elements("uls(identifier)", Elements::UnorderedList, identifier, 'ul')
        end

       #
        # platform method to retrieve the text from an ordered list
        # See PageObject::Accessors#ordered_list
        #
        def ordered_list_text_for(identifier)
          process_watir_call("ol(identifier).text", Elements::OrderedList, identifier, nil, 'ol')
        end

        #
        # platform method to retrieve an ordered list element
        # See PageObject::Accessors#ordered_list
        #
        def ordered_list_for(identifier)
          find_watir_element("ol(identifier)", Elements::OrderedList, identifier, 'ol')
        end
        
        #
        # platform method to retrieve an array of ordered lists
        #
        def ordered_lists_for(identifier)
          find_watir_elements("ols(identifier)", Elements::OrderedList, identifier, 'ol')
        end

        #
        # platform method to retrieve the text for a h1
        # See PageObject::Accessors#h1
        #
        def h1_text_for(identifier)
          process_watir_call("h1(identifier).text", Elements::Heading, identifier, nil, 'h1')
        end
        
        #
        # platform method to retrieve the h1 element
        # See PageObject::Accessors#h1
        #
        def h1_for(identifier)
          find_watir_element("h1(identifier)", Elements::Heading, identifier, 'h1')
        end  

        #
        # platform method to retrieve an array of h1s
        #
        def h1s_for(identifier)
          find_watir_elements("h1s(identifier)", Elements::Heading, identifier, 'h1')
        end

        #
        # platform method to retrieve the text for a h2
        # See PageObject::Accessors#h2
        #
        def h2_text_for(identifier)
          process_watir_call("h2(identifier).text", Elements::Heading, identifier, nil, 'h2')
        end
        
        #
        # platform method to retrieve the h2 element
        # See PageObject::Accessors#h2
        #
        def h2_for(identifier)
          find_watir_element("h2(identifier)", Elements::Heading, identifier, 'h2')
        end  

        #
        # platform method to retrieve an array of h2s
        #
        def h2s_for(identifier)
          find_watir_elements("h2s(identifier)", Elements::Heading, identifier, 'h2')
        end

        #
        # platform method to retrieve the text for a h3
        # See PageObject::Accessors#h3
        #
        def h3_text_for(identifier)
          process_watir_call("h3(identifier).text", Elements::Heading, identifier, nil, 'h3')
        end
        
        #
        # platform method to retrieve the h3 element
        # See PageObject::Accessors#h3
        #
        def h3_for(identifier)
          find_watir_element("h3(identifier)", Elements::Heading, identifier, 'h3')
        end  

        #
        # platform method to retrieve an array of h3s
        #
        def h3s_for(identifier)
          find_watir_elements("h3s(identifier)", Elements::Heading, identifier, 'h3')
        end

        #
        # platform method to retrieve the text for a h4
        # See PageObject::Accessors#h4
        #
        def h4_text_for(identifier)
          process_watir_call("h4(identifier).text", Elements::Heading, identifier, nil, 'h4')
        end
        
        #
        # platform method to retrieve the h4 element
        # See PageObject::Accessors#h4
        #
        def h4_for(identifier)
          find_watir_element("h4(identifier)", Elements::Heading, identifier, 'h4')
        end  

        #
        # platform method to retrieve an array of h4s
        #
        def h4s_for(identifier)
          find_watir_elements("h4s(identifier)", Elements::Heading, identifier, 'h4')
        end

        #
        # platform method to retrieve the text for a h5
        # See PageObject::Accessors#h5
        #
        def h5_text_for(identifier)
          process_watir_call("h5(identifier).text", Elements::Heading, identifier, nil, 'h5')
        end
        
        #
        # platform method to retrieve the h5 element
        # See PageObject::Accessors#h5
        #
        def h5_for(identifier)
          find_watir_element("h5(identifier)", Elements::Heading, identifier, 'h5')
        end  

        #
        # platform method to retrieve an array of h5s
        #
        def h5s_for(identifier)
          find_watir_elements("h5s(identifier)", Elements::Heading, identifier, 'h5')
        end

        #
        # platform method to retrieve the text for a h6
        # See PageObject::Accessors#h6
        #
        def h6_text_for(identifier)
          process_watir_call("h6(identifier).text", Elements::Heading, identifier, nil, 'h6')
        end
        
        #
        # platform method to retrieve the h6 element
        # See PageObject::Accessors#h6
        #
        def h6_for(identifier)
          find_watir_element("h6(identifier)", Elements::Heading, identifier, 'h6')
        end  

        #
        # platform method to retrieve an array of h6s
        #
        def h6s_for(identifier)
          find_watir_elements("h6s(identifier)", Elements::Heading, identifier, 'h6')
        end

        #
        # platform method to retrieve the text for a paragraph
        # See PageObject::Accessors#paragraph
        #
        def paragraph_text_for(identifier)
          process_watir_call("p(identifier).text", Elements::Paragraph, identifier, nil, 'p')
        end
        
        #
        # platform method to retrieve the paragraph element
        # See PageObject::Accessors#paragraph
        #
        def paragraph_for(identifier)
          find_watir_element("p(identifier)", Elements::Paragraph, identifier, 'p')
        end

        #
        # platform method to retrieve an array of paragraph elements
        #
        def paragraphs_for(identifier)
          find_watir_elements("ps(identifier)", Elements::Paragraph, identifier, 'p')
        end

        #
        # platform method to return the text for a label
        # See PageObject::Accessors#label
        #
        def label_text_for(identifier)
          process_watir_call("label(identifier).text", Elements::Label, identifier, nil, 'label')
        end

        #
        # platform method to return a PageObject::Elements::Label element
        # See PageObject::Accessors#label
        #
        def label_for(identifier)
          find_watir_element("label(identifier)", Elements::Label, identifier, 'label')
        end

        #
        #
        # platform method to retrieve an array of label elements
        #
        def labels_for(identifier)
          find_watir_elements("labels(identifier)", Elements::Label, identifier, 'label')
        end

        #
        # platform method to set the file on a file_field element
        # See PageObject::Accessors#file_field
        #
        def file_field_value_set(identifier, value)
          process_watir_call("file_field(identifier).set(value)", Elements::FileField,
                             identifier, value)
        end

        #
        # platform method to retrieve a file_field element
        # See PageObject::Accessors#file_field
        #
        def file_field_for(identifier)
          find_watir_element("file_field(identifier)", Elements::FileField, identifier)
        end

        #
        # platform method to retrieve an array of file field elements
        #
        def file_fields_for(identifier)
          find_watir_elements("file_fields(identifier)", Elements::FileField, identifier)
        end

        #
        # platform method to click on an area
        #
        def click_area_for(identifier)
          process_watir_call("area(identifier).click", Elements::Area, identifier, nil, 'area')
        end

        #
        # platform method to retrieve an area element
        #
        def area_for(identifier)
          find_watir_element("area(identifier)", Elements::Area, identifier, 'area')
        end

        #
        # platform method to retrieve an array of area elements
        #
        def areas_for(identifier)
          find_watir_elements("areas(identifier)", Elements::Area, identifier, 'area')
        end

        #
        # platform method to retrieve a canvas element
        #
        def canvas_for(identifier)
          find_watir_element("canvas(identifier)", Elements::Canvas, identifier, 'canvas')
        end

        #
        # platform method to retrieve an array of canvas elements
        #
        def canvass_for(identifier)
          find_watir_elements("canvases(identifier)", Elements::Canvas, identifier, 'canvas')
        end

        #
        # platform method to retrieve an audio element
        #
        def audio_for(identifier)
          find_watir_element("audio(identifier)", Elements::Audio, identifier, 'audio')
        end

        #
        # platform method to retrieve an array of audio elements
        #
        def audios_for(identifier)
          find_watir_elements("audios(identifier)", Elements::Audio, identifier, 'audio')
        end

        #
        # platform method to retrieve a video element
        #
        def video_for(identifier)
          find_watir_element("video(identifier)", Elements::Video, identifier, 'video')
        end

        #
        # platform method to retrieve an array of video elements
        #
        def videos_for(identifier)
          find_watir_elements("videos(identifier)", Elements::Video, identifier, 'video')
        end

        #
        # platform method to return a PageObject::Elements::Element element
        # See PageObject::Accessors#element
        #
        def element_for(tag, identifier)
          find_watir_element("#{tag.to_s}(identifier)", Elements::Element, identifier, tag.to_s)
        end

        #
        # platform method to return an array of  PageObject::Elements::Element elements
        # See PageObject::Accessors#element
        #
        def elements_for(tag, identifier)
          find_watir_elements("#{tag.to_s}s(identifier)", Elements::Element, identifier, tag.to_s)
        end

        #
        # platform method to return a svg element
        #
        def svg_for(identifier)
          find_watir_element("element(identifier)", Elements::Element, identifier)
        end
 
        #
        # platform method to return an array of svg elements
        #
        def svgs_for(identifier)
          find_watir_elements("element(identifier)", Elements::Element, identifier)
        end
 
        private

        def move_element_to_css_selector(the_call, identifier)
          valid_elements = %w(
            area audio canvas div
            h1 h2 h3 h4 h5 h6
            label li p span td video
          )
          element = the_call.split('(').first
          if identifier.keys.include?(:css) and valid_elements.include? element
            the_call[element] = 'element'
            selectors = identifier[:css].split(/,\s*/).map { |selector|
              modified_selector = selector.split /\s+/
              last = modified_selector.pop
              if last.index(element) == 0
                selector
              else
                modified_selector.push(element + last)
              end
            }
            identifier[:css] = selectors.join(', ')
          end
          [the_call, identifier]
        end
    
        def find_watir_elements(the_call, type, identifier, tag_name=nil)
          identifier, frame_identifiers = parse_identifiers(identifier, type, tag_name)
          the_call, identifier = move_element_to_css_selector(the_call, identifier)
          elements = @browser.instance_eval "#{nested_frames(frame_identifiers)}#{the_call}"
          switch_to_default_content(frame_identifiers)
          elements.map { |element| type.new(element, :platform => :watir_webdriver) }
        end

        def find_watir_element(the_call, type, identifier, tag_name=nil)
          identifier, frame_identifiers = parse_identifiers(identifier, type, tag_name)
          the_call, identifier = move_element_to_css_selector(the_call, identifier)
          element = @browser.instance_eval "#{nested_frames(frame_identifiers)}#{the_call}"
          switch_to_default_content(frame_identifiers)
          type.new(element, :platform => :watir_webdriver)
        end

        def process_watir_call(the_call, type, identifier, value=nil, tag_name=nil)
          identifier, frame_identifiers = parse_identifiers(identifier, type, tag_name)
          the_call, identifier = move_element_to_css_selector(the_call, identifier)
          value = @browser.instance_eval "#{nested_frames(frame_identifiers)}#{the_call}"
          switch_to_default_content(frame_identifiers)
          value
        end

        def parse_identifiers(identifier, element, tag_name=nil)
          frame_identifiers = identifier.delete(:frame)
          identifier = add_tagname_if_needed identifier, tag_name if tag_name
          identifier = element.watir_identifier_for identifier
          return identifier, frame_identifiers
        end

        def add_tagname_if_needed identifier, tag
          return identifier if identifier.length < 2 and not identifier[:name]
          identifier[:tag_name] = tag if identifier[:name]
          identifier
        end
    
        def nested_frames(frame_identifiers)
          return if frame_identifiers.nil?
          frame_str = ''
          frame_identifiers.each do |id|
            value = id.values.first
            frame_str += "frame(:#{id.keys.first} => #{value})." if value.to_s.is_integer
            frame_str += "frame(:#{id.keys.first} => '#{value}')." unless value.to_s.is_integer
          end
          frame_str
        end
        
        def switch_to_default_content(frame_identifiers)
          @browser.wd.switch_to.default_content unless frame_identifiers.nil?          
        end

        def css_element
          "element(identifier)"
        end

        def css_elements
          "elements(identifier)"
        end

        def call_for_watir_element(identifier, call)
          identifier[:css] ? "#{css_element}" : call
        end

        def call_for_watir_elements(identifier, call)
          identifier[:css] ? "#{css_elements}" : call          
        end

        def switch_to_frame(frame_identifiers)
          unless frame_identifiers.nil?
            frame_identifiers.each do |frame_id|
              value = frame_id.values.first
              @browser.wd.switch_to.frame(value)
            end
          end          
        end
      end
    end
  end
end