# $Id: Blob.pm,v 1.1.1.1 2001/06/04 23:39:28 proclus Exp $

package BB::Blob;
use strict;

#
# Wrapper for gnuplot-like control files
#

require Executer;
use Logger;

sub new {
	my ($proto, $name) = @_;
	my $type = ref($proto) || $proto;
	my $this = bless({}, $type);

	$this -> {theName} = $name;
	$this -> {theExpMask} = undef;
	$this -> {theHead} = [];
	$this -> {theBody} = [];
	$this -> {theTail} = [];

	$this -> {theRunCallBack} = undef; # used in run()/finishRun()

	return $this;
}

sub clone {
	my ($this, $cfg) = @_;

	my $clone = bless({}, ref($this));

	# simple members
	foreach (qw(theName theExpMask theRunCallBack)) {
		$clone->{$_} = $this -> {$_};
	}
	# arrays of commands
	$clone->{theHead} = BB::Tools::CloneArr($this->{theHead}, {});
	$clone->{theBody} = BB::Tools::CloneArr($this->{theBody}, {});
	$clone->{theTail} = BB::Tools::CloneArr($this->{theTail}, {});

	$clone->configure($cfg);

	return $clone;
}

sub name {
	my ($this, $name) = @_;
	$this->{theName} = $name if defined $name;
	return $this->{theName};
}

sub exp_mask {
	my ($this, $exp_mask) = @_;
	$this->{theExpMask} = $exp_mask if defined $exp_mask;
	return $this->{theExpMask};
}

sub head {
	my ($this, $head) = @_;
	$this->{theHead} = $head if defined $head;
	return $this->{theHead};
}

sub body {
	my ($this, $body) = @_;
	$this->{theBody} = $body if defined $body;
	return $this->{theBody};
}

sub tail {
	my ($this, $tail) = @_;
	$this->{theTail} = $tail if defined $tail;
	return $this->{theTail};
}

sub configure {
	my ($this, $cfg) = @_;

	$this->{theName} = BB::Tools::EvalVars($this->{theName}, $cfg);
	$this->{theExpMask} = BB::Tools::EvalVars($this->{theExpMask}, $cfg);
	$this->configureCmds($cfg);
}

sub configureCmds {
	my ($this, $cfg) = @_;

	my %c = %{$cfg};
	$c{'name'} = $this->{theName};
	$c{'exp_mask'} = $this->{theExpMask};
	$this->forEach('configure', \%c);
}

sub forEach {
	my ($this, $method, @params) = @_;

	my @res = ();
	foreach (@{$this->{theHead}}, @{$this->{theBody}}, @{$this->{theTail}}) {
		push @res, $_->$method(@params);
	}
	
	return @res;
}

sub run {
	my ($this, $call_back) = @_;
	die() unless defined $call_back;
	$this->{theRunCallBack} = $call_back;

	&Logf('starting blob: %s', $this->{theName});

	BB::Executer::RunSeq($this->{theHead});
	BB::Executer::RunPar($this->{theBody}, \&finishRun, $this);
}

sub finishRun {
	my $this = shift;
	die() unless $this;

	BB::Executer::RunSeq($this->{theTail});

	my $call_back = $this->{theRunCallBack};
	die() unless defined $call_back;
	delete $this->{theRunCallBack};

	&Logf("blob done: %s", $this->{theName});

	&{$call_back}($this);
}

1;
