package DX::Step::Backtrack;

use DX::DependencyMap;
use DX::Utils qw(format_deps compact_deps);
use DX::Class;

with 'DX::Role::Step';

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

sub apply_to {
  my ($self, $ss) = @_;
  my $rspace = $self->resolution_space;
  trace backtrack => [ statement => [
    [ symbol => 'backtrack' ],
    [ 'enter_block' ]
  ] ];
  trace backtrack => [ word_and_body => [
    'failure_dependencies',
    format_deps($rspace->geometry_depends_on)
  ] ];
  my $dmap = DX::DependencyMap->new_empty
                              ->with_dependencies_for(
                                  backtrack => $rspace->geometry_depends_on
                                );
  DECISION: foreach my $adj (@{$ss->decisions_taken}) {
    my ($rspace_was, $ss_was) = @$adj;
    trace backtrack => [ statement => [
      [ symbol => 'decision' ],
      [ pairs => [
        [ for => $rspace_was->proposition, ]
          #aperture => 
      ] ]
    ] ];
    foreach my $event (@{$rspace_was->aperture}) {
      if ($dmap->dependents_of($event)) {
        my $remain = $rspace_was->remaining_resolution_space;
        if (@{$remain->members}) {
          trace backtrack => [ statement => [
            [ symbol => 'found_alternative' ]
          ] ];
          trace backtrack => [ 'leave_block' ];
          return $ss_was->but(
            next_step => $remain->with_geometry_dependencies(
                                  $dmap->dependencies_for('backtrack')
                               )->next_step
          );
        }
        $dmap = $dmap->with_dependencies_for(
          backtrack => $rspace_was->geometry_depends_on
        );
        trace backtrack => [ word_and_body => [
          'failure_dependencies',
          format_deps(compact_deps($dmap->dependencies_for('backtrack')))
        ] ];
        next DECISION;
      }
    }
    trace backtrack => [ statement => [ [ symbol => 'non_relevant' ] ] ];
  }
  trace backtrack => [ statement => [ [ symbol => 'exhaustion' ] ] ];
  trace backtrack => [ 'leave_block' ];
  return $ss->but(
    next_step
      => $ss->on_exhaustion_step->but(
           exhaustion_depends_on => $dmap->dependencies_for('backtrack')
         )
  );
}

1;
