require 'criteria'

module Criteria
  class ArrayTable < Table
    def initialize(array)
      super()
      @criterion_type = ArrayCriterion
      @array          = array
    end

    def method_missing(m)
      criterion       = super
      criterion.array = @array
      return criterion
    end #m:method_missing
  end #c:ArrayTable


  class ArrayCriterion < Criterion
    attr_accessor :array

    def select(*args)
      result = []
      filter = (args.size > 0)

      @array.each {
        | o |
        if(self._apply(o))
          if filter
            a = []
            args.each { |m| a << o.__send__(m) }
            result << a
          else
            result << o
          end
        end
      }

      return result
    end #m:select

    def _apply(ob)
      chain = @chain.map { |i|
        i.is_a?(ArrayCriterion) ? i._apply(ob) : i
      }

      if(@field.is_a? ArrayCriterion)
        res = @field._apply(ob)
      else
        res = ob.__send__(@field)
      end

      return res.__send__(chain.shift, *chain)
    end #m:_apply

    def method_missing(m, *args)
      cri       = super
      cri.array = array
      return cri
    end #m:method_missing
  end #c:ArrayCriterion
end #M:Criteria
