module RSpec
  module Core
    module DSL
      def self.browser
        @browser
      end
      def self.set_browser(browser)
        @browser = browser
      end

      module_eval do
        BASE = File.expand_path(File.dirname(__FILE__) + '/..')
        define_method('screen_shot') { |i='No Description Provided'|
          file = "#{BASE}/images/#{Token.provide}.png"
          FileUtils.mkdir File.dirname(file) unless File.directory?(File.dirname(file))
          @__cucumber_step_mother.add_image(:src => file, :label => i)
          File.open(file, 'w+') do |fd|
            fd.write RSpec::Core::DSL.browser.driver.screenshot_as(:png)
          end
        }
        define_method('site_requires') {
          Find.find(BASE + '/sites').each { |i|
           require i if i =~ /\.rb$/ && !File.directory?(i) && i !~ /\/features\//
          } 
        }

        define_method('load_fixtures') {
          @test_data = {}
          Dir.entries(BASE + '/sites').each { |site|
            next if site == '.' or site == '..' or !File.directory?(BASE + "/sites/#{site}")
            @test_data[site] = {}

            Dir.entries(BASE + "/sites/#{site}/conf/").each { |i|
              next unless i =~ /.yaml$|.yml$/
              cfg = YAML::load_file(BASE + "/sites/#{site}/conf/#{i}")
              k = i.split(".").first.to_sym
              @test_data[site].merge!({k => cfg})
            }

          }
        }

        define_method('site_objects') {
          flows = []
          Find.find(BASE + '/sites').each { |i|
            next unless i =~ /\/flows\/.+\.rb$/
            content = File.read(i)
            if content.grep(/module/).length > 1 || content.grep(/module/).length == 0
              raise StandardError, "Flows can only contain 1 module, where the module name is the site name" 
            end
            __module = content.grep(/^module/).first.split(' ').last
            __class = content.grep(/class/).first.split(' ').last
            eval("@#{__module.downcase}_#{__class.downcase} = #{__module}::#{__class}.new")
            flows << eval("@#{__module.downcase}_#{__class.downcase}")
            eval("@#{__module.downcase}_#{__class.downcase}.instance_variable_set('@__cucumber_step_mother', @__cucumber_step_mother)")
            eval("@#{__module.downcase}_#{__class.downcase}.instance_variable_set('@browser', @browser)")
            eval("@#{__module.downcase}_#{__class.downcase}.instance_variable_set('@test_data', @test_data)")
            instance_vars = []
            c =<<-EOF
              @#{__module.downcase}_#{__class.downcase}.elements.instance_variables.each { |v| instance_vars << v.to_s.gsub(/@/, '') }
            EOF
            eval(c)

            instance_vars.each { |v|
              eval("@#{__module.downcase}_#{__class.downcase}.elements.#{v}.instance_variable_set('@browser', @browser)")
              eval("@#{__module.downcase}_#{__class.downcase}.elements.#{v}.instance_variable_set('@test_data', @test_data)")
            }

            eval("@#{__module.downcase}_#{__class.downcase}.elements.instance_variable_set('@browser', @browser)")
            eval("@#{__module.downcase}_#{__class.downcase}.elements.instance_variable_set('@test_data', @test_data)")
          } 
          flows.each { |flow|
            manipulate = flows.dup
            manipulate.delete(flow)
            manipulate.each { |add_to|
              name = flow.class.to_s.split('::').join('_').downcase
              add_to.send(:instance_variable_set, "@#{name}", flow)
            }
          }
        }
      end
    end
  end
end