#!/usr/bin/perl
#
# Copyright (c) 2020  Peter Pentchev <roam@ringlet.net>
# This code is hereby licensed for public consumption under either the
# GNU GPL v2 or greater, or Larry Wall's Artistic license - your choice.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.

use v5.12;

use strict;
use warnings;

use File::Temp;
use Path::Tiny;
use Test::Command;
use Test::More;

my $have_mp3_info = 1;
eval "use MP3::Info;";
if ($@) {
	$have_mp3_info = 0;
}

plan tests => 2;

my $RE_TAG = qr{^
	(?<tag>
		Song \s Title
		|
		[A-Za-z]+
	)
	: \s
	(?<value_full>
		(?<ws_before> \s* )
		(?<value> .*? )
		(?<ws_after> \s* )
	)
$}x;

sub extract_file_tag_stripped($)
{
	my ($lines) = @_;

	my %data;
	subtest 'parse an RFC-822-like tag' => sub {
		if (!@{$lines}) {
			fail 'any lines';
			return;
		}

		while (@{$lines}) {
			my $line = shift @{$lines};
			last if $line eq '';
			if ($line !~ $RE_TAG) {
				like $line, $RE_TAG, 'tag: value line';
				return;
			}
			my ($tag, $value) = ($+{tag}, $+{value});
			ok 1, "got a $tag line";
			$data{$tag} = $value;
		}
		fail 'any tag/value lines' unless %data;
	};

	return \%data;
}

my $PROG = $ENV{TEST_ID3} // './id3';
BAIL_OUT "Not an executable file: $PROG" unless -f $PROG && -x $PROG;

SKIP: {
	skip 'no MP3::Info module', 2 unless $have_mp3_info;

	my $orig = path($ENV{TEST_ID3_FILE} //
	    '/usr/share/doc/libjs-scriptaculous/test/functional/sword.mp3.gz');
	BAIL_OUT "Not a file: $orig" unless $orig->is_file;
	my $is_gzipped = substr($orig->basename, -3) eq '.gz';
	my $fname = $is_gzipped ? substr($orig->basename, 0, -3) : $orig->basename;

	my $tempd = File::Temp->newdir('id3test.XXXXXX', TMPDIR => 1);
	my $fdata = path($tempd)->child($fname);
	
	if ($is_gzipped) {
		my $gztemp = $fdata->sibling($orig->basename);
		$orig->copy($gztemp);
		my $res = system { 'gzip' } ('gzip', '-d', '--', $gztemp);
		BAIL_OUT "oof, gzip result $res" unless $res == 0;
	} else {
		$orig->copy($fdata);
	}
	BAIL_OUT "Could not create $fdata" unless $fdata->is_file;

	my $exp = MP3::Info->new("$fdata");
	is $exp->FILE, "$fdata", "MP3::Info parsed $fdata";

	subtest 'List the tag' => sub {
		plan tests => 5;

		my $cmd = [$PROG, '--', $fdata];
		my $tcmd = Test::Command->new(cmd => $cmd);
		$tcmd->exit_is_num(0, 'succeeded');

		my @lines = split /\r*\n/, $tcmd->stdout_value;
		ok @lines >= 2, 'output at least two lines';

		my $tag = extract_file_tag_stripped \@lines;
		ok scalar keys %{$tag} >= 5, 'output at least five tags';

		subtest 'compare the keys' => sub {
			plan tests => scalar keys %{$tag};

			for my $key (sort keys %{$tag}) {
				my $value = $tag->{$key};
				my $upper = uc $key;
				if ($key eq 'Filename') {
					$upper = 'FILE';
				} elsif ($key eq 'Song Title') {
					$upper = 'TITLE';
				} elsif ($key eq 'Note') {
					$upper = 'COMMENT';
				} elsif ($key eq 'Genre') {
					$value = (split / [(]/, $value)[0];
				}
				is $value, $exp->{$upper}, "compare $key";
			}
		};
	};
}
