#!/usr/bin/perl -w

# This sample script shows how to build up a project tree structure
# using VC::CMSynergy::traverse_project. We use a simple minded
# Node class for the tree structure.
# Kudos go to Anne Feldmeier for the simple tree building algorithm.

=head1 NAME

project_tree - build a project tree

=head1 SYNOPSIS

project_tree [options] project

  project     project spec, either in the form "proj_vers"
              or as four part objectname

  Common options:

  -D PATH | --database PATH       database path
  -H HOST | --host HOST           engine host
  -U NAME | --user NAME           user name
  -P STRING | --password STRING   user's password
  --ui_database_dir PATH          path to copy database information to

  Options:

  -r          recurse into sub projects

=cut

use Getopt::Long qw(:config bundling);
use Pod::Usage;
use VCS::CMSynergy 1.18 qw(:cached_attributes :tied_objects);
use VCS::CMSynergy::Helper; 
use strict;

# a simple tree node class
{
    package Node;

    sub new
    {
	my ($class, $object, $parent) = @_;
	my $self = bless { object => $object, parent => $parent }, $class;
	push @{ $parent->{children} }, $self if $parent;
	$self;
    }

    sub object 		{ shift->{object}; }
    sub parent 		{ shift->{parent}; }
    sub children	{ shift->{children}; }
}

my %ccm_opts = VCS::CMSynergy::Helper::GetOptions;

my $recursive;
(GetOptions(
    'r|recursive'	=> \$recursive,		# include subprojects
) && @ARGV == 1) or pod2usage(2);
my ($project) = @ARGV;

my @attributes = qw(owner modify_time);		# just an example

my $ccm = VCS::CMSynergy->new(
    %ccm_opts,
    RaiseError	=> 1,
    PrintError	=> 0);

my Node $root;		# the root of the project tree
my Node $top;		# node corresponding to top of Traversal::dirs stack

$ccm->traverse_project(
    {
	subprojects	=> $recursive,
	attributes	=> \@attributes,
	wanted		=> sub
	{
	    return if $_->cvtype eq "project";	# skip subprojects

	    unless ($root)
	    {
		$root = $top = Node->new($_);
		return;
	    }

	    # traversal may have moved up in the project tree,
	    # so $top may not correspond to the top of
	    # the directory stack anymore
	    my $topdir = $VCS::CMSynergy::Traversal::dirs[-1];
	    $top = $top->parent while $top->object ne $topdir;

	    # create a Node with $top as the parent
	    my $node = Node->new($_, $top);
	    
	    # move $top when we're on a directory,
	    # because traversal will immediately descent into it
	    $top = $node if $_->cvtype eq "dir";
	},
    },
    $project
);

print_tree($root, "");

exit(0);

# simple recursive tree walk
sub print_tree
{
    my ($node, $indent) = @_;

    my $obj = $node->object;
    print $indent, join(" ", $obj->name, $obj->cvtype, @$obj{@attributes}), "\n";

    if ($node->children)
    {
	$indent .= "  ";
	print_tree($_, $indent) foreach @{ $node->children };
    }
}
