package DX::Solver;

use DX::RuleSet;
use DX::State;
use DX::ResultStream;
use List::Util qw(reduce);
use Moo;

has rule_set => (is => 'lazy', handles => [ 'add_rule' ], builder => sub {
  DX::RuleSet->new
});

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

has observation_policy => (is => 'ro');

sub query {
  my ($self, $vars, @terms) = @_;
  my $rule_set = $self->rule_set;
  my $head = reduce { $b->but(next => $a) }
               reverse map $rule_set->expand(@$_), @terms;
  my $state = DX::State->new(
    next_op => $head,
    return_stack => [],
    by_id => {},
    scope => {},
    last_choice => [],
    facts => $self->facts,
    rule_set => $rule_set,
  )->assign_vars(map +($_ => {}), @$vars);
  return DX::ResultStream->new(
    for_state => $state,
    ($self->observation_policy
      ? (observation_policy => $self->observation_policy)
      : ()),
  );
}

1;
