package DX::Op::MemberOf;

use DX::ArrayStream;
use DX::RefSet;
use Moo;

with 'DX::Role::Op';

has member_var => (is => 'ro', required => 1);
has coll_var => (is => 'ro', required => 1);

sub run {
  my ($self, $state) = @_;
  ($state, my %args) = $self->_expand_args($state,
    member => $self->member_var,
    of => $self->coll_var
  );
  my ($member, $of) = @args{qw(member of)};
  my $type = $state->resolve_value($of);
  my $set = ref($type) ? $type : $state->facts->{$type};
  if ($member->is_bound) {
    my $test = $state->resolve_value($member);
    if (grep { $_ eq $test } $set->all) {
      return $state->then($self->next);
    }
    return $state->backtrack;
  }
  my $ref_set = (
    ref($type)
      ? $set
      : DX::RefSet->new(
          target => $type, names => [ $set->key_list ],
        )
  );
  return $state->then($self->next)
               ->add_dependencies($member->id, $of->id)
               ->bind_root_set($member->id, $ref_set)
}

1;
