package DX::RuleDefinitionContext;

use DX::PropositionSequence;
use DX::Predicate::Rule;
use DX::Class;

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

has proposition_sequence => (is => 'rwp', lazy => 1, builder => sub {
  my ($self) = @_;
  my %arg_names = map +($_ => 1), @{$self->arg_names};
  DX::PropositionSequence->new_empty
                         ->but(external_names => \%arg_names);
});

has expander => (is => 'ro', required => 1, handles => [ qw(expand_args) ]);

sub apply_predicate {
  my ($self, $pred, @arg_strings) = @_;
  my @args = $self->expand_args(@arg_strings);
  my ($intro, $need) = ({}, {});
  foreach my $arg (@args) {
    next if ref($arg);
    next if $arg =~ /^\??[a-z]/; # skip globals
    # ?Foo is intro, Foo is need
    ($arg =~ s/^\?// ? $intro : $need)->{$arg} = 1;
  }
  my $prop = DX::Proposition->new(
    predicate => $pred,
    args => \@args,
    introduced_names => $intro,
    required_names => $need,
  );
  $self->_set_proposition_sequence(
    $self->proposition_sequence->with_additional_proposition($prop)
  );
  return;
}

sub bake_rule {
  my ($self) = @_;
  DX::Predicate::Rule->new(
    arg_names => $self->arg_names,
    proposition_sequence => $self->proposition_sequence
  );
}

1;
