package ID3FS::Path;

use strict;
use warnings;
use feature 'switch';
use ID3FS::PathElement::Artist;
use ID3FS::PathElement::Album;
use ID3FS::PathElement::Boolean;
use ID3FS::PathElement::File;
use ID3FS::PathElement::Tag;
use ID3FS::PathElement::Tagval;

our ($STATE_INVALID, $STATE_ROOT, $STATE_TAG, $STATE_TAGVAL,
     $STATE_BOOLEAN, $STATE_ARTISTS, $STATE_ALBUMS, $STATE_TRACKLIST,
     $STATE_FILE)=(0..9);

sub new
{
    my $proto=shift;
    my $class=ref($proto) || $proto;
    my $self={};
    bless($self,$class);

    $self->{db}=shift;
    $self->{path}=shift;
    $self->parse();
    print "STATE: ", $self->state(), "\n";
    return $self;
}

sub isdir
{
    my($self)=@_;
    if(($self->state() eq $STATE_FILE) ||
       ($self->state() eq $STATE_INVALID))
    {
	return 0;
    }
    return 1;
}

sub isvalid
{
    my($self)=@_;
    return($self->state() != $STATE_INVALID);
}

sub dest
{
    my($self)=@_;
    if($self->state() == $STATE_FILE)
    {
	return $self->{db}->filename(@{$self->{elements}});
    }
    return "ERROR"; #should never happen?
}

sub dirents
{
    my($self)=@_;
    my @dents=();
    given($self->state())
    {
	when($STATE_TAG)
	{
	    @dents=qw(AND ARTISTS ALBUMS TRACKS);
	}
	when($STATE_BOOLEAN)
	{
	    @dents=$self->{db}->tags(@{$self->{elements}});
	}
	when($STATE_ROOT)
	{
	    @dents=("ALL", $self->{db}->tags(@{$self->{elements}}));
	}
	when($STATE_ARTISTS)
	{
	    @dents=$self->{db}->artists(@{$self->{elements}});
	}
	when($STATE_ALBUMS)
	{
	    @dents=$self->{db}->albums(@{$self->{elements}});
	}
	when($STATE_TRACKLIST)
	{
	    @dents=$self->{db}->tracks(@{$self->{elements}});
	}
	default
	{
	    print "DIRENTS: UNHANDLED STATE: $_\n";
	}
    }
    return(@dents);
}

sub parse
{
    my($self)=@_;
    @{$self->{components}}=split(/\//, $self->{path});
    shift @{$self->{components}}; # drop empty field before leading /
    print "PATH: $self->{path}\n";
#    print "COMPONENTS: ", join(' | ', @{$self->{components}}), "\n";
    $self->state($STATE_ROOT);
    return if($self->{path} eq "/");
    my @parts=@{$self->{components}};
    my($tag, $tagval);
    $self->{elements}=[];
    while(my $name=shift @parts)
    {
	print "NAME: $name\n";
	given($self->state())
	{
	    when($STATE_INVALID)
	    {
		print "SM: INVALID: $name\n";
		return;
	    }
	    when($STATE_ROOT)
	    {
		print "SM: ROOT: $name\n";
		if($name eq "ALL")
		{
		    $self->state($STATE_ARTISTS);
		}
		else
		{
		    $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
		    if($tag)
		    {
			push(@{$self->{elements}}, $tag);
			$self->state($STATE_TAG);
		    }
		    else
		    {
			$self->state($STATE_INVALID);
		    }
		}
	    }
	    when($STATE_TAG)
	    {
		print "SM: TAG: $name\n";
		given($name)
		{
		    when("AND")
		    {
			$self->state($STATE_BOOLEAN);
#			push(@{$self->{elements}}, ID3FS::PathElement::Boolean->new($name));
		    }
		    when("ARTISTS")
		    {
			$self->state($STATE_ARTISTS);
		    }
		    when("ALBUMS")
		    {
			$self->state($STATE_ALBUMS);
		    }
		    when("TRACKS")
		    {
			$self->state($STATE_TRACKLIST);
		    }

#		    when("OR")  { ; }
#		    when("NOT") { ; }
		    default
		    {
			$self->state($STATE_INVALID);
		    }
		}
	    }

	    when(255) #FIXME - dead code
	    {
		print "SM: WANTMORE: $name\n";
		$tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
		if($tag)
		{
		    push(@{$self->{elements}}, $tag);
#		    $self->state($STATE_TAG);
		}
		else
		{
		    $self->state($STATE_INVALID);
		}
		my @valid_tagvals=$self->{db}->tag_values($tag);
		print "TAGVALUES: $name: ", join(', ', @valid_tagvals), "\n";
		if(@valid_tagvals)
		{
		    if(grep { $name eq $_; } @valid_tagvals)
		    {
			print "TAGVAL VALID\n";
			$self->state($STATE_TAGVAL);
			push(@{$self->{elements}}, ID3FS::PathElement::Tagval($name));
		    }
		    else
		    {
			print "ERROR: unknown tagval: $tagval\n";
			$self->state($STATE_INVALID);
		    }
		}
		else
		{
		    $self->state($STATE_INVALID);
		}
	    }
	    when($STATE_TAGVAL)
	    {
		print "SM: TAGVAL: $name\n";
	    }
	    when($STATE_BOOLEAN)
	    {
		print "SM: BOOLEAN: $name\n";
		my $tag=ID3FS::PathElement::Tag->new($self->{db}, $name);
		if($tag)
		{
		    push(@{$self->{elements}}, $tag);
		    $self->state($STATE_TAG);
		}
		else
		{
		    $self->state($STATE_INVALID);
		}
	    }
	    when($STATE_ARTISTS)
	    {
		print "SM: ARTIST: $name\n";
		my $artist=ID3FS::PathElement::Artist->new($self->{db}, $name);
		push(@{$self->{elements}}, $tag);
		if($artist)
		{
		    push(@{$self->{elements}}, $artist);
		    $self->state($STATE_ALBUMS);
		}
		else
		{
		    $self->state($STATE_INVALID);
		}
	    }
	    when($STATE_ALBUMS)
	    {
		print "SM: ALBUM: $name\n";
		my $album=ID3FS::PathElement::Album->new($self->{db}, $name);
		push(@{$self->{elements}}, $album);
		if($album)
		{
		    push(@{$self->{elements}}, $album);
		    $self->state($STATE_TRACKLIST);
		}
		else
		{
		    $self->state($STATE_INVALID);
		}
	    }
	    when($STATE_TRACKLIST)
	    {
		print "SM: TRACKS: $name\n";
		my $track=ID3FS::PathElement::File->new($self->{db}, $name);
		push(@{$self->{elements}}, $track);
		if($track)
		{
		    push(@{$self->{elements}}, $track);
		    $self->state($STATE_FILE);
		}
		else
		{
		    $self->state($STATE_INVALID);
		}
	    }
	    when($STATE_FILE)
	    {
		print "SM: FILE: $name\n";
		# Can't have anything after a filename
		$self->state($STATE_INVALID);
	    }
	    default
	    {
		print "SM: ERROR: UNKNOWN STATE: $self->{state}\n";
		$self->state($STATE_INVALID);
	    }
	}
    }
}

sub state
{
    my($self, $newstate)=@_;
    $self->{state}=$newstate if(defined($newstate));
    return $self->{state};
}

1;
