module SpecEmberHelpers
  def ember_store
    h = page.evaluate_script <<-SCRIPT
      $s = (window.MozoUser || App).__container__.lookup('store:main');
      JSON.stringify({
        lists: $s.all('list').invoke('serialize'),
        orders: $s.all('order').invoke('serialize'),
        product_orders: $s.all('product_order').invoke('serialize'),
        product_categories: $s.all('product_category').invoke('serialize'),
        products: $s.all('product').invoke('serialize'),
        sections: $s.all('section').invoke('serialize'),
        tables: $s.all('table').invoke('serialize')
      })
    SCRIPT
    JSON.parse(h)
  end

  def assert_element_class(selector, expected_class_names)
    find selector # capybara wait for element
    time = 0
    expected_class_names = Array.wrap(expected_class_names).sort
    found_classes = page.evaluate_script("$('#{selector}').attr('class')").to_s.split(/\s+/).sort
    while (found_classes & expected_class_names) != expected_class_names and time < 10
      sleep 0.1
      found_classes = page.evaluate_script("$('#{selector}').attr('class')").to_s.split(/\s+/).sort
      time += 1
    end
    (found_classes & expected_class_names).sort.should eq expected_class_names
  end

  # expect_that_eventually selector: '.supplier-orders-placed-count-number', has_text: "10"
  def expect_that_eventually(options = {})
    selector = options[:selector] or raise "An argument selector: '.my-selector' is required"
    time = 0
    expected_value, value_method = case options
      when ->(h){ h.has_key? :has_text } then [options[:has_text], 'text()']
      when ->(h){ h.has_key? :has_value } then [options[:has_value], 'val()']
      else
        raise "No matcher can be found, possible matchers: :has_text, ..."
    end
    current_value = page.evaluate_script("$('#{selector}').#{value_method}")
    while current_value != expected_value and time < 30
      sleep 0.1
      current_value = page.evaluate_script("$('#{selector}').text()")
      time += 1
    end
    #current_value.should eq expected_text
    #if expected_text = options[:has_text]
      #current_value = page.evaluate_script("$('#{selector}').#{value_method}")
      #while current_text != expected_text and time < 30
        #sleep 0.1
        #current_text = page.evaluate_script("$('#{selector}').text()")
        #time += 1
      #end
      #current_text.should eq expected_text
    #else
      #raise "No matcher can be found, possible matchers: :has_text, ..."
    #end
  end

  def js_set_field(selector, value)
    find selector
    page.execute_script("$('#{selector}').val('#{value}').trigger('change')")
  end

  def js_click(selector)
    find selector
    page.execute_script "$('#{selector}').click()"

    # Wait for jQuery activity to finish
    wait_cycles = 0
    active_count = page.evaluate_script '$.active'
    while active_count > 0 and wait_cycles < 30
      sleep 0.1
      active_count = page.evaluate_script '$.active'
      wait_cycles += 1
    end
    raise "There are still active jQuery tasks" if active_count > 0
  end

  def js_text(selector)
    find selector
    page.evaluate_script("$('#{selector}').text()")
  end

  def ember_find(typeKey, id)
    h = page.evaluate_script "(window.MozoUser || App).__container__.lookup('service:store').peekRecord('#{typeKey}', '#{id}').toJSON()"
  end

  def ember_all(typeKey)
    h = page.evaluate_script <<-SCRIPT
      (window.MozoUser || App).__container__.lookup('service:store').peekAll('#{typeKey}').map(function(r){ result = r.toJSON(); result['id'] = r.id; return result })
    SCRIPT
  end

  def js_path
    page.evaluate_script 'location.pathname + location.hash'
  end

  def faye_log
    JSON.parse(page.evaluate_script(%|JSON.stringify(window.faye_log)|))
  end

  def when_ember_is_ready(&blk)
    times = 0
    ember_ready = page.evaluate_script('window.ember_ready')
    while not ember_ready or times < 30
      sleep 0.1
      ember_ready = page.evaluate_script('window.ember_ready')
      times += 1
    end
    raise "Ember is not loaded and should be" unless ember_ready
    blk.call
  end
end
