require 'set'

class Decomposer

  def initialize params
    @uv_gen = params[:uv_gen]
    @qu_gen = params[:qu_gen]
    @qv_gen = params[:qv_gen]
  end

  def each
    @uv_gen.each do |u, v|
      @qu_gen.each u, v do |qu|
        @qv_gen.each u, v, qu do |g, qv|
          yield [u, v, qu, g, qv]
        end
      end
    end
  end

end



describe Decomposer do

  context 'given that the three generators are working properly' do

    before do
      @uv_gen = mock 'UVGenerator'
      @qu_gen = mock 'QuGenerator'
      @qv_gen = mock 'QvGenerator'
      @qu1, @qu2, @g1, @g2, @qv1, @qv2 = mock('Blanket'), mock('Blanket'), mock('Blanket'), mock('Blanket'), mock('Blanket'), mock('Blanket')
    end

    it 'should poll the generators and yield the resulting decompositions one by one' do
      @uv_gen.should_receive(:each).and_yield([0,1,2], [3]).and_yield [0,1], [2,3]
      @qu_gen.should_receive(:each).with([0,1,2], [3]).and_yield @qu1
      @qu_gen.should_receive(:each).with([0,1], [2,3]).and_yield @qu2
      @qv_gen.should_receive(:each).with([0,1,2], [3], @qu1).and_yield @g1, @qv1
      @qv_gen.should_receive(:each).with([0,1], [2,3], @qu2).and_yield @g2, @qv2
      decomposer = Decomposer.new :uv_gen => @uv_gen, :qu_gen => @qu_gen, :qv_gen => @qv_gen
      result = []
      decomposer.each { |dec| result << dec }
      result.first.should == [[0,1,2], [3], @qu1, @g1, @qv1]
      result.last.should  == [[0,1], [2,3], @qu2, @g2, @qv2]
    end

    it 'should poll the generators and yield the resulting decompositions one by one' do
      @uv_gen.stub!(:each).and_yield([0,1,2], [3]).and_yield [0,1], [2,3]
      @qu_gen.stub!(:each).with([0,1,2], [3]).and_yield @qu1
      @qu_gen.stub!(:each).with([0,1], [2,3]).and_yield @qu2
      @qv_gen.stub!(:each).with([0,1,2], [3], @qu1).and_yield @g1, @qv1
      @qv_gen.stub!(:each).with([0,1], [2,3], @qu2).and_yield @g2, @qv2
      enumerator = Decomposer.new(:uv_gen => @uv_gen, :qu_gen => @qu_gen, :qv_gen => @qv_gen).to_enum
      enumerator.next.should == [[0,1,2], [3], @qu1, @g1, @qv1]
      enumerator.next.should == [[0,1], [2,3], @qu2, @g2, @qv2]
    end

  end

end
