require 'active_support/concern'

module Softwear::Library
  module Spec
    extend ActiveSupport::Concern

    module CapybaraHelpers
      def wait_for_ajax
        begin
          Timeout.timeout(Capybara.default_wait_time) do
            wait_for_jquery
            loop until finished_all_ajax_requests?
          end
        rescue
          sleep 0.1
        end
      end

      def finished_all_ajax_requests?
        page.evaluate_script('jQuery.active').zero?
      end

      def wait_for_redirect
        original_url = current_path
        until current_path != original_url
          sleep(0.1)
        end
      end

      def wait_for_jquery
        until page.evaluate_script('jQuery.active') == 0
          sleep(0.1)
        end
      end

      def accept_alert
        page.evaluate_script('window.confirm = function() { return true; }')
        yield
      end

      def dismiss_alert
        page.evaluate_script('window.confirm = function() { return false; }')
        yield
        # Restore existing default
        page.evaluate_script('window.confirm = function() { return true; }')
      end

      def eventually_fill_in(field, options={})
        page.should have_css('#' + field)
        fill_in field, options
      end

      def within_row(num, &block)
        if RSpec.current_example.metadata[:js]
          within("table.index tbody tr:nth-child(#{num})", &block)
        else
          within(:xpath, all('table.index tbody tr')[num-1].path, &block)
        end
      end

      def column_text(num)
        if RSpec.current_example.metadata[:js]
          find("td:nth-child(#{num})").text
        else
          all('td')[num-1].text
        end
      end

      def find_label_by_text(text, options = {})
        label = find_label(text)

        if !options[:try] && label.nil?
          raise "Could not find label by text #{text}"
        end

        label
      end

      def find_label(text)
        first(:xpath, "//label[text()[contains(.,'#{text}')]]")
      end

    end

    module Select2
      def select2(text, options)
        label = find_label_by_text(options[:from], try: true)
        if label
          selector = "select[name='#{label['for']}']+span,select[id='#{label['for']}']+span"
        else
          selector = "#{options[:from]}+span"
        end

        if options[:last]
          all(selector).last.click
        else
          find(selector).click
        end

        old_scopes = page.instance_variable_get(:@scopes)
        page.instance_variable_set(:@scopes, [nil])

        find('input.select2-search__field').set(text)
        sleep options[:wait_before_click] if options[:wait_before_click]
        result = first('li.select2-results__option')
        if result.nil? || result.text == "No results found"
          raise %(No results matching "#{text}" found during select2)
        else
          result.click
        end

      ensure
        page.instance_variable_set(:@scopes, old_scopes) if old_scopes
      end
    end

    included do
      RSpec.configure do |config|
        config.include CapybaraHelpers, type: :feature
      end
    end

  end
end