#!/usr/bin/perl -w

package TreeMenu;
use strict;
use warnings;
use Carp;

sub new_child
{
    my ( $Tree, $Number ) = @_[0..1];
    my $Dispatch = $Tree->{ 'dispatch' };

    my $this = $Tree->{ 'children' }[ $Number ];
    ref( $this ) or croak "Out of select";

    ref( $this ) eq 'ARRAY' and 
        $this = $Dispatch->ChildArray( $this );

    $this->{'dispatch'} = $Dispatch;
    $this->{'path'} = $Tree->{'path'};
    $this->{'level'} = $Tree->{'level'} + 1;
    $this->{'sel'} = [ @{$Tree->{'sel'}}, $Number ];
    $this->{'seltx'} = $Tree->{'seltx'} eq '' ? $Number :
        $Tree->{'seltx'} . "/$Number";
    $this->{'num'} = $Number;

    $this = bless( $this, ref( $Tree )  );
    $Tree->{ 'children' }[ $Number ] = $this;
    return $this;
}

sub new
{
    my ( $class, $this, $Dispatch ) = @_[0..2];

    ref( $this ) eq 'ARRAY' and $this = $Dispatch->ChildArray( $this );

    $this->{ 'dispatch' } = $Dispatch;
    $this->{ 'path' } = './';
    $this->{ 'level' } = 0;
    $this->{ 'sel' } = [];
    $this->{ 'seltx' } = '';

    return bless( $this, ref( $class ) || $class );
};

sub update_content
{
    my $this = shift;

    if( defined( $this->{'datfile'} ) )
    {
        my $data = do( $this->{'path'}. $this->{'datfile'} ) or
            croak "Read of $this->{'path'}$this->{'datfile'} failed\n($@)";

        $this->{'datfile'} =~ /^(.*\/)[^\/]+$/ and $this->{'path'} .= $1;
        foreach my $k ( keys( %{$data} ) )
        {
            exists( $this->{$k} ) or $this->{$k} = $data->{$k};
        }
        delete( $this->{'datfile'} );
    }

    defined( $this->{'children'} ) and !ref($this->{'children'}) and
        $this->{'children'} = $this->{'dispatch'}->ScalarChildren( $this, @_ );
    return $this;
}

sub Process
{
    my $this = shift;
    my $Expand  = shift;

    $this->update_content();
    $this->{ 'dispatch' }->Node( $this, @_ );

    foreach my $i ( @{$Expand} )
    {
        $this = $this->new_child( $i + 0 );
        $this->update_content();
        $this->{ 'dispatch' }->Node( $this, @_ );
    }

    #leaves
    my $children = $this->{ 'children' };
    my $t = 0;
    my $Dispatch = $this->{ 'dispatch' };
    my $method;

    $Dispatch->StartLeaves( $this, @_ );
    while( $t <= $#{$children} )
    {
        if( ref( $children->[$t] ) )    # subfolder
        {
            $Dispatch->Leaf( $this->new_child( $t ), @_ );
            ++ $t;
        }
        else
        {
            $method = $$children[$t];
            $Dispatch->$method($children->[$t+1], $this, @_);
            $t += 2;
        }
    }
    $Dispatch->EndLeaves( $this, @_ );
}

1;
