package App::Commentry::CommentSet;

use aliased 'App::Commentry::Comment';
use JSON;
use File::Spec;
use File::Path;
use File::Copy;
use Moo;

has base_dir => (is => 'ro', required => 1);
has path => (is => 'ro', required => 1);

has _json => (is => 'lazy');

sub _build__json { JSON->new->utf8->pretty->convert_blessed }

has _members => (is => 'lazy');

sub _filename {
  my ($self) = @_;
  File::Spec->catfile($self->base_dir, $self->path.'.json');
}

sub _build__members {
  my ($self) = @_;
  my $file = $self->_filename;
  return [] unless -e $file;
  my $text = do {
    open my $in, '<', $file
      or die "Couldn't open ${file}: $!";
    local $/; <$in>;
  };
  [ map Comment->new($_), @{$self->_json->decode($text)} ];
}

sub _write {
  my ($self) = @_;
  my $file = $self->_filename;
  mkpath((File::Spec->splitpath($file))[1]);
  open my $out, '>', "${file}.new"
    or die "Couldn't open ${file}.new to write: $!";
  print $out $self->_json->encode($self->_members);
  move("${file}.new", $file);
}

sub flatten {
  my ($self) = @_;
  @{$self->_members};
}

sub map {
  my ($self, $mapping) = @_;
  require App::Commentry::MappedSet;
  App::Commentry::MappedSet->new(source => $self, mapping => $mapping);
}

sub add {
  my ($self, $params) = @_;
  push @{$self->_members}, my $new = Comment->new($params);
  $self->_write;
  $new;
}

1;
