package DX::ShellState;

use DX::Utils qw(deparse);
use DX::Class;

has template_query_state => (
  is => 'ro', required => 1, isa => QueryState
);

has current_query_state => (
  is => 'lazy', builder => 'new_query_state', isa => QueryState
);

has trace_these => (
  is => 'ro', required => 1, isa => HashRef[Str],
);

has mode => (is => 'ro', required => 1, isa => ShellMode);

sub new_query_state { $_[0]->template_query_state }

sub trace_sub {
  my ($self) = @_;
  sub {
    my ($tag, $thing) = @_;
    my ($part) = split /\./, $tag;
    my $traces = $self->trace_these;
    return unless $traces->{$part} or $traces->{'*'} or $ENV{DX_TRACE};
    my $dp = deparse($thing);
    $dp =~ s/\n$//;
    warn "${dp}\n";
  }
}

sub with_trace_changes {
  my ($self, @changes) = @_;
  my %trace = %{$self->trace_these};
  foreach my $change (@changes) {
    if ($change =~ /^\+?(\S+)/) {
      $trace{$1} = 1;
    } elsif ($change =~ /^-(\S+)/) {
      delete $trace{$1};
    }
  }
  return $self->but(trace_these => \%trace);
}

sub with_new_query_state {
  my ($self) = @_;
  $self->but(
    current_query_state => $self->new_query_state
  );
}

sub with_mode {
  my ($self, $new_mode) = @_;
  return (
    $self->but(mode => $new_mode),
    [ mode => $new_mode ],
  );
}

1;
