module FormTester

  def fill_in_form(data, selector_lambda = -> (camelcase_name) { "##{camelcase_name}" })
    upload_fields = data.extract!(:UPLOAD_FIELDS).values[0]
    if upload_fields
      upload_fields.each { |field| upload_image_stub(field, selector_lambda) }
    end
    data.each do |field_name, field_value|
      selector = field_selector_by_data(field_name)
      begin
        element = find(selector, wait: 4)
      rescue Capybara::Ambiguous, Capybara::ElementNotFound
        element = find(selector, visible: false)
      end
      case element.tag_name
        when "input"
          element.set(field_value, clear: :backspace)
        when "textarea"
          element.set(field_value, clear: :backspace)
        when "select"
          change_nice_select_option(field_value, element)
      end
    end
  end

  def new_fill_in_form(data, selector_lambda = -> (camelcase_name) { "*[data-field=\"#{camelcase_name}\"]" })
    upload_fields = data.extract!(:UPLOAD_FIELDS).values[0]
    if upload_fields
      upload_fields.each { |field| upload_image_stub(field, selector_lambda) }
    end
    data.each do |field_name, field_value|
      selector = field_selector(field_name, selector_lambda)
      begin
        element = find(selector, wait: 4)
      rescue Capybara::Ambiguous, Capybara::ElementNotFound
        element = find(selector, visible: false)
      end
      case element.tag_name
        when "input"
          element.set(field_value, clear: :backspace)
        when "textarea"
          element.set(field_value, clear: :backspace)
        when "select"
          change_nice_select_option(field_value, element)
      end
    end
  end

  def expect_form_errors(errors)
    errors.each { |error| expect_content_on_page(error) }
  end

  def expect_form_values(form_data)
    form_data.except(:UPLOAD_FIELDS).values.all? { |val| page_has_field_value?(val) }
  end

  private

  def upload_image_stub(upload_field_name, selector_lambda)
    selector = field_selector(upload_field_name, selector_lambda)
    upload_button = find("#{selector} a.change-upload")
    upload_button.click
    wait_for_ajax
  end

  def page_has_field_value?(value)
    has_field_value = page.has_content?(value) || page.has_selector?("input[value='#{value}']")
    expect(has_field_value).to be(true)
  end

  def field_selector (field_name, selector_lambda)
    camelcase_field_name = coerced_camelize(field_name)
    selector_lambda.call(camelcase_field_name)
  end

  def field_selector_by_data(field_name)
    "[data-field='#{field_name.to_s}']"
  end

  def coerced_camelize(text)
    text = text.to_s
    text.gsub(/\s/, '_').camelize(:lower)
  end
end
