package TestSupport;

use strict;
use warnings;
use File::Temp qw(tempdir);
use File::Path;
use File::Basename;
use File::Copy qw(move);
use Test::More;
use autodie;

use Exporter qw(import);
our @EXPORT_OK = qw(create_test_files delete_test_files move_test_files
  modify_attrs_on_test_files $dir received_events receive_event);

our $dir = tempdir(CLEANUP => 1);
my $size = 1;

sub create_test_files {
	my (@files) = @_;

	for my $file (@files) {
		my $full_file = File::Spec->catfile($dir, $file);
		my $full_dir = dirname($full_file);

		mkpath $full_dir unless -d $full_dir;

		my $exists = -e $full_file;

		open my $fd, ">", $full_file;
		print $fd "Test\n" x $size++ if $exists;
		close $fd;
	}
}

sub delete_test_files {
	my (@files) = @_;

	for my $file (@files) {
		my $full_file = File::Spec->catfile($dir, $file);
		if   (-d $full_file) { rmdir $full_file; }
		else				   { unlink $full_file; }
	}
}

sub move_test_files {
	my (%files) = @_;

	while (my ($src, $dst) = each %files) {
		my $full_src = File::Spec->catfile($dir, $src);
		my $full_dst = File::Spec->catfile($dir, $dst);
		move $full_src, $full_dst;
	}
}

sub modify_attrs_on_test_files {
	my (@files) = @_;

	for my $file (@files) {
		my $full_file = File::Spec->catfile($dir, $file);
		chmod 0750, $full_file or die "Error chmod on $full_file: $!";
	}
}

our @received = ();
our @expected = ();
our @msgs	 = ();
our $cv;

sub receive_event {
	push @received, @_;
	push @msgs,
	  "--- received: " . join(',', map { $_->type . ":" . $_->path } @_);
	$cv->end for @_;
}

sub received_events {
	my ($sub, $desc, @expected) = @_;

	$cv = AnyEvent->condvar;
        $cv->begin;
	$cv->begin for @expected;

	$sub->();

	my $w = AnyEvent->timer(
		after => 1,
		cb	=> sub { $cv->end });

	$cv->recv;

	my @received_type = map { $_->type } @received;
	compare_ok(\@received_type, \@expected, $desc) or do {
		diag sprintf "... expected: %s\n... received: %s\n",
		  join(',', @expected), join(',', @received_type);
		diag join "\n", @msgs;
	};

	@received = ();
	@msgs	 = ();
}

sub compare_ok {
	my ($rec_ref, $exp_ref, $desc) = @_;
	$desc ||= "compare arrays";
	my @rec = @$rec_ref;
	my @exp = @$exp_ref;

	while(scalar @rec or scalar @exp){
		no warnings 'uninitialized';
		my ($rec,$exp) = (shift @rec, shift @exp);
		next if $rec eq $exp || "$rec?" eq $exp;
		if($exp =~ /\?$/){ # optional
			unshift @rec, $rec if defined $rec;
			next;
		}
		return ok(0, $desc);
	}

	return ok(1, $desc);
}

1;
