package DX::Deparse;

use DX::Class;

sub indent_by { '    ' }

sub max_width { 78 }

sub _inner_meta {
  my ($self, $ometa) = @_;
  +{ %$ometa, width_left => $ometa->{width_left} - length $self->indent_by };
}

sub _indent_one {
  my ($self, $to_indent) = @_;
  $to_indent =~ s/^/${\$self->indent_by}/mg;
  $to_indent;
}

sub fmt {
  my ($self, $thing) = @_;
  $self->_fmt($thing, { width_left => $self->max_width })."\n";
}

sub _fmt {
  my ($self, $thing, $meta) = @_;
  return $thing unless ref($thing);
  my $type = join'_', split '::', lc +(ref($thing) =~ /^DX::(.*)/)[0];
  $self->${\"_fmt_${type}"}($thing, $meta);
}

sub _fmt_value_dict {
  my ($self, $dict, $ometa) = @_;
  my $imeta = $self->_inner_meta($ometa);
  my $chunks = $self->_indent_one(join "\n", map {
    "$_ ".$self->_fmt($dict->get_member_at($_), $imeta)
  } $dict->index_list);
  "{{\n${chunks}\n}}";
}

sub _fmt_value_string {
  my ($self, $string) = @_;
  my $val = $string->string_value;
  if ($val =~ /^\w+$/) {
    qq{'${val}'}
  } else {
    qq{{'${val}'}}
  }
}

sub _fmt_value_number { $_[1]->number_value }

sub _fmt_value_true { 'true' }

sub _fmt_value_false { 'false' }

sub _fmat_value_unset { 'unset' }

1;
