package DX::ResolutionSpace;

use DX::Step::Backtrack;
use DX::Step::ResolveProposition;
use DX::Utils qw(expand_deps);
use DX::Class;

has proposition => (is => 'ro', isa => Proposition);

has geometry_depends_on => (is => 'ro', required => 1, isa => DependencyList);

has aperture => (is => 'ro', required => 1, isa => ApertureList);

has members => (
  is => 'ro', required => 1, isa => ArrayRef[ResolutionStrategy|Resolution]
);

sub for_deparse {
  my ($self) = @_;
  [ statement => [
    [ symbol => 'resolution_space' ],
    [ pairs => [
      [ proposition => $self->proposition ],
      [ geometry_depends_on => [ block => [
        map [ statement => [
          [ symbol => (split '::', ${$_->[0]})[-1] ],
          [ value_path => [ @{$_}[1..$#$_] ] ],
        ] ], @{expand_deps($self->geometry_depends_on)}
      ] ] ],
      (@{$self->aperture}
        ? [ aperture => [ block => [
            map [ statement => [
              [ symbol => (split '::', ${$_->[0]})[-1] ],
              [ value_path => [ @{$_}[1..$#$_] ] ],
            ] ], @{$self->aperture}
          ] ] ]
        : ()),
      [ members => [ block => [ @{$self->members} ] ] ]
    ] ],
  ] ];
}

sub next_resolution {
  my ($self) = @_;
  return undef unless my ($first) = @{$self->members};
  return $first->next_resolution;
}

sub remaining_resolution_space {
  my ($self) = @_;
  die "Sense makes not" unless my ($first, @rest) = @{$self->members};
  return $self->but(members => [ $first->remainder, @rest ]);
}

sub next_step {
  my ($self) = @_;
  my $step_type = (@{$self->members} ? 'ResolveProposition' : 'Backtrack');
  return "DX::Step::${step_type}"->new(resolution_space => $self);
}

1;
