package DX::ActionBuilder::Normal;

use DX::Action::SetValue;
use DX::Action::AddValue;
use DX::Utils qw(:event_types);
use DX::Class;

with 'DX::Role::ActionBuilder';

has target_path => (is => 'ro', required => 1, isa => ValuePath);

sub aperture_for_set_value {
  [ [ VALUE_SET ,=> @{$_[0]->target_path} ] ]
}

sub action_for_set_value {
  my ($self, $value) = @_;
  DX::Action::SetValue->new(
    target_path => $self->target_path,
    new_value => $self->apply_to_value($value),
  );
}

sub aperture_for_add_member {
  my ($self, $at) = @_;
  [ [ VALUE_EXISTS ,=> @{$self->target_path}, $at ] ]
}

sub action_for_add_member {
  my ($self, $at, $value) = @_;
  my $ab = $self->specialize_for_member($at);
  DX::Action::AddValue->new(
    target_path => $ab->target_path,
    new_value => $ab->apply_to_value($value),
  );
}

sub action_for_remove_member { die 'WHUT' }

sub apply_to_value {
  my ($self, $value) = @_;
  my $new_value = $value->but_set_action_builder($self);
  return $new_value unless $new_value->isa('DX::Value::Dict');
  my %m = %{$new_value->members};
  return $new_value->but(
    members => {
      map +($_ => $self->specialize_for_member($_)->apply_to_value($m{$_})),
        keys %m,
    },
  );
}

sub specialize_for_member {
  my ($self, $at) = @_;
  $self->but(
    target_path => [
      @{$self->target_path},
      (ref($at) ? $at->string_value : $at)
    ],
  );
}

1;
