# -*- mode: perl; coding: utf-8 -*-
package YATT::Util::DirTreeBuilder;
use strict;
use warnings FATAL => qw(all);

use base qw(YATT::Class::Configurable File::Spec);
BEGIN {require Exporter; *import = \&Exporter::import}
our @EXPORT_OK = qw(tmpbuilder);

use YATT::Fields qw(^cf_DIR cf_TESTNO cf_AUTO_REMOVE);
use overload '&{}' => 'as_sub';
use File::Remove qw(remove);
use Carp;

sub tmpbuilder {
  my ($tmpdir) = @_;
  unless (-d $tmpdir) {
    mkdir $tmpdir or die "Can't mkdir $tmpdir: $!";
  }
  MY->new(DIR => $tmpdir, TESTNO => 0
	  , AUTO_REMOVE => !$ENV{DEBUG_TMP});
}

sub DESTROY {
  my MY $self = shift;
  remove \1, $self->{cf_DIR} if $self->{cf_AUTO_REMOVE};
}

sub as_sub {
  my MY $self = shift;
  my $basedir = $self->{cf_DIR} . '/t' . ++$self->{cf_TESTNO};
  unless (-d $basedir) {
    mkdir $basedir or die "Can't mkdir $basedir! $!";
  }
  sub {
    $self->build($basedir, @_);
    if (wantarray) {
      ($basedir, sub {
	 $self->build($basedir, [FILE => @_])
       });
    } else {
      $basedir;
    }
  }
}

sub build {
  my ($self, $basedir, @action) = @_;
  foreach my $action (@action) {
    next unless ref $action eq 'ARRAY';
    my $sub = $self->can("build_" . $action->[0])
      or die "Invalid builder spec: $action->[0]";
    $sub->($self, $basedir, @{$action}[1 .. $#$action]);
  }
}

sub build_DIR {
  my ($self, $basedir, $name, @action) = @_;
  my $dir = "$basedir/$name";
  unless (-d $dir) {
    mkdir($dir) or die "Can't mkdir $dir: $!";
  }
  $self->build($dir, @action);
}

sub build_FILE {
  my ($self, $basedir, $name, @body) = @_;
  my $fn = "$basedir/$name";
  open(my $out, '>', $fn), "file  $fn" or die "Can't create $fn: $!";
  print $out @body;
}

sub path2desc {
  my ($self, $path, $content) = @_;
  $self->path2desc_1([$self->splitdir($path), $content]);
}

sub path2desc_1 {
  my ($self, $desc) = @_;
  if (@$desc > 2) {
    [DIR => shift @$desc
     , $self->path2desc_1($desc)];
  } else {
    unshift @$desc, 'FILE';
    $desc;
  }
}

1;
