class Usher
  class Route

    module Util

      class Group < Array
        attr_accessor :group_type
        attr_accessor :parent

        def inspect
          "#{group_type}->#{super}"
        end

        def initialize(group_type, parent)
          @group_type = group_type
          @parent = parent
        end
      end

      def self.cartesian_product!(lval, rval)
        product = []
        (lval.size * rval.size).times do |index|
          val = []
          val.push(*lval[index % lval.size])
          val.push(*rval[index / lval.size])
          product << val
        end
        lval.replace(product)
      end

      def self.expand_path(parts)
        if parts.is_a?(Array)
          paths = [[]]
          
          unless parts.respond_to?(:group_type)
            new_parts = Group.new(:any, nil)
            parts.each{|p| new_parts << p}
            parts = new_parts
          end
          
          case parts.group_type
          when :all
            parts.each do |p|
              cartesian_product!(paths, expand_path(p))
            end
          when :any
            parts.each do |p|
              cartesian_product!(paths, expand_path(p))
            end
            paths.unshift([])
          when :one
            cartesian_product!(paths, parts.collect do |p|
              expand_path(p)
            end)
          end
          paths.each{|p| p.compact!; p.flatten! }
          paths
        else
          [[parts]]
        end

      end
    end
  end
end