using Loom::DSL

class Neuronset

  cluster :cluster do

    object :string
    object :split_string, :class => Hash
    object :parse_tree, :class => Hash
    object :seed_tree, :class => Hash
    object :parse_tree_shallow, :class => Hash
    object :hash_rep, :class => Hash

    from :string do

      get :parse_tree do
        routine { Parser.parse(string) }
      end

    end

    from :parse_tree do

      get :hash_rep do
        routine do
          # binding.pry
          trans = Parslet::Transform.new do
            rule(:region => subtree(:x)) { Hash[ region: Region::Cluster.new(parse_tree: x).build(:hash_rep) ] }
            rule(:chemical_profile => subtree(:x)) { Hash[ chemical_profile: Chemical::Cluster.new(parse_tree: x).build(:hash_rep) ] }
            rule(:misc => subtree(:x)) { Hash[ misc: Misc::Cluster.new(parse_tree: x).build(:hash_rep) ] }
            rule(:type_id => simple(:x)) { x }
          end.apply(parse_tree)
          trans.is_a?(Array) ? trans.reduce(:+) : trans
        end
      end

    end

    from :hash_rep do
      # get :string do
      #   routine do
      #     region_str = Region::Cluster.new(hash_rep: hash_rep[:region]).build(:string) if hash_rep[:region]
      #     type_str = hash_rep[:types].join('/') if hash_rep[:types]
      #     chemical_str = Chemical::Cluster.new(hash_rep: hash_rep[:chemical_profile]).build(:string) if hash_rep[:chemical_profile]
      #     misc_str = Misc::Cluster.new(hash_rep: hash_rep[:misc]).build(:string) if hash_rep[:misc]
      #     [region_str, type_str, chemical_str, misc_str].compact.join('/')
      #   end
      # end

      get :split_string do
        routine do
          split_string = Hash.new
          split_string[:region] = Region::Cluster.new(hash_rep: hash_rep[:region]).build(:string) if hash_rep[:region]
          split_string[:types] = hash_rep[:types].join('/') if hash_rep[:types]
          split_string[:chemical] = Chemical::Cluster.new(hash_rep: hash_rep[:chemical_profile]).build(:string) if hash_rep[:chemical_profile]
          split_string[:misc] = Misc::Cluster.new(hash_rep: hash_rep[:misc]).build(:string) if hash_rep[:misc]
          split_string
        end
      end
    end

    from :split_string do
      get :string do routine { split_string.values.join('/') } end
    end

    from :string, :parse_tree, :hash_rep do
      get :seed_tree do
        routine do
          # elements are single-pair hashes
          subtrees = Hash[ parse_tree.map { |e| [e.keys.first, e.values.first] } ]
          # binding.pry
          tree = Hash.new
          tree[:name] = string
          tree[:types] = hash_rep[:types].map(&:to_i) if hash_rep[:types]
          tree[:chemical] = Chemical::Cluster.new(parse_tree: subtrees[:chemical_profile]).build(:seed_tree) if subtrees[:chemical_profile]
          tree[:region] = Region::Cluster.new(parse_tree: subtrees[:region]).build(:seed_tree) if subtrees[:region]
          tree[:misc] = Misc::Cluster.new(parse_tree: subtrees[:misc]).build(:seed_tree) if subtrees[:misc]
          # Hash[
          #   name: string,
          #   types: hash_rep[:types].andand.map(&:to_i),
          #   chemical: Chemical::Cluster.new(parse_tree: subtrees[:chemical_profile]).build(:seed_tree),
          #   region: Chemical::Cluster.new(parse_tree: subtrees[:chemical_profile]).build(:seed_tree),
          #   misc: Chemical::Cluster.new(parse_tree: subtrees[:chemical_profile]).build(:seed_tree),
          # ]
          tree
        end
      end
    end

  end

end
