package DX::Step::ResolveProposition;

use DX::Step::EnterRecheck;
use DX::Step::CompleteResolution;
use DX::Step::Backtrack;

use DX::Utils qw(expand_deps);

use DX::Class;

with 'DX::Role::Step';

has resolution_space => (is => 'ro', isa => ResolutionSpace);

sub but_first {
  my ($self, @actions) = @_;
  $self->but(actions => [ @actions, @{$self->actions} ]);
}

sub but_with_dependencies_on {
  my ($self, @deps) = @_;
  $self->but(depends_on => [ @{$self->depends_on}, @deps ]);
}

sub apply_to {
  my ($self, $old_ss) = @_;
  my $rspace = $self->resolution_space;
  my $prop = $rspace->proposition;
  my $res = $rspace->next_resolution;
  my $vdeps = $res->veracity_depends_on;
  trace resolve => [ statement => [
    [ symbol => 'resolve' ],
    [ block => [
      [ statement => [
        [ symbol => 'proposition' ],
        @{$prop->for_deparse->[1]},
      ] ],
      (@{$res->actions}
        ? [ statement => [
            [ symbol => 'actions' ],
            [ block => $res->actions ],
          ] ]
        : ()),
      [ statement => [
        [ symbol => 'depends_on' ],
        [ block => [
          map [ statement => [
            [ symbol => (split '::', ${$_->[0]})[-1] ],
            [ value_path => [ @{$_}[1..$#$_] ] ]
          ] ], @{$vdeps}
        ] ],
      ] ],
    ] ]
  ] ];
  my $old_hyp = $old_ss->current_hypothesis;
  (my $hyp, my @recheck) = $old_hyp->with_resolution(
    $prop, $vdeps, $res->actions
  );
  # Failure to have a $hyp here means an action was disallowed by policy
  # or failed - unsure if "failed" should be permitted and unsure if policy
  # checks belong in with_resolution
  unless ($hyp) {
    return $old_ss->but(
      next_step
        => $rspace->remaining_resolution_space->next_step
    );
  }
  my $next_step = DX::Step::CompleteResolution->new(
    original_search_state => $old_ss,
    resolution_space => $rspace,
  );
  unless (@recheck) {
    return $old_ss->but(next_step => $next_step, current_hypothesis => $hyp);
  }
  return $old_ss->but(
    current_hypothesis => $hyp,
    next_step => DX::Step::EnterRecheck->new(
      proposition_list => \@recheck,
      on_completion_step => $next_step,
      resolution_space => $rspace,
    ),
  );
}

1;
