package ID3FS::Path::Node;

use strict;
use warnings;

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

    $self->left(shift);
    $self->op(shift);
    $self->right(shift);

    return $self;
}

sub set
{
    my($self, $name, $val)=@_;
    if(defined($val))
    {
	$self->{$name}=$val;
    }
    return $self->{$name};
}

sub left  { return shift->set("left",  shift); }
sub right { return shift->set("right", shift); }
sub op    { return shift->set("op",    shift); }

sub print
{
    my($self)=@_;
    my $op=$self->op();
    my $left=$self->left();
    my $right=$self->right();
    return "" unless($left || $right);
    my $str .= $self->print_node($left);
    $str .= (" " . $op->{name} . " ") if($op);
    $str .= $self->print_node($right);
    if($op || ($left && $right))
    {
	$str="(" . $str . ")";
    }
    return $str;
}

sub print_node
{
    my($self, $node)=@_;
    return "" unless(defined($node));
    return $node->print() if(ref($node) eq "ID3FS::Path::Node");
    return $node->{name};
}

sub to_sql
{
    my($self, $not, @joins)=@_;
    $not=0 unless(defined($not));
    my @outjoins=();
    # init
    unless(@joins)
    {
	@outjoins = @joins = ("INNER");
    }
    my $left=$self->left();
    my $right=$self->right();
    return ("", @outjoins) unless($left || $right);
    my ($leftstr, @leftjoins) = $self->node_to_sql($left, $not, @joins);
    push(@joins, @leftjoins);
    push(@outjoins, @leftjoins);
    my $op=$self->op();
    if(defined($op))
    {
	if($op->{name} eq "AND")
	{
	    push(@joins, "INNER");
	    push(@outjoins, "INNER");
	}
	elsif($op->{name} eq "NOT")
	{
	    $not=1;
	    push(@joins, "LEFT");
	    push(@outjoins, "LEFT");
#	    print("LEFT: ", $left->print(), "\n") if ($left);
#	    print("RIGHT: ", $right->print(), "\n") if($right);
	}
    }
    my ($rightstr, @rightjoins) = $self->node_to_sql($right, $not, @joins);
    push(@outjoins, @rightjoins);
#    print "LEFT (", scalar(@leftjoins), "): $leftstr\n";
#    print "RIGHT (", scalar(@rightjoins), "): $rightstr\n";
    my $str=$leftstr;
    $str .= (" " . $op->{name} . " ") if($op && !$not);
    $str .= $rightstr;
    if($op || ($left && $right))
    {
	$str="(" . $str . ")";
    }
#    print "STR: $str\n";
    return($str, @outjoins);
}

sub node_to_sql
{
    my($self, $node, $not, @joins)=@_;
    return ("", ()) unless(defined($node));
    return $node->to_sql($not, @joins) if(ref($node) eq "ID3FS::Path::Node");
    my $sql;
    my $cnt=scalar(@joins)+1;
    if(defined($node->{parents_id}))
    {
	$sql= "(t" . scalar(@joins) . ".parents_id='$node->{parents_id}'";
	$sql .= " AND fxt" . scalar(@joins) . ".tags_id='" . $node->{id} . "'";
    }
    else
    {
	$sql= "(t" . scalar(@joins) .".parents_id=''";
	$sql .= " AND fxt" . scalar(@joins) . ".tags_id='" . $node->{id} . "'";
    }
    if($not)
    {
	$sql .= " AND fxt" . scalar(@joins) . ".files_id IS NULL";
    }
    $sql .= ")";
    return ($sql, ());
}

sub used_tags
{
    my($self)=@_;
    my @used=(grep { defined; }  ($self->node_used_tags($self->left()),
				  $self->node_used_tags($self->right())));
    return(@used);
}

sub node_used_tags
{
    my($self, $node)=@_;
    return (undef) unless(defined($node));
    return $node->used_tags() if(ref($node) eq "ID3FS::Path::Node");
    if(defined($node->{parents_id}))
    {
	return([ $node->{parents_id}, $node->{id} ]);
    }
    return $node->{id};
}


sub max
{
    my($self, $a, $b)=@_;
    return(($a > $b) ? $a : $b);
}

1;
