package RFC::GasGroup;
#$Id: GasGroup.pm,v 1.35 2015/08/19 08:27:10 sqko Exp $

############################################################################
#
#
#    RFC::GasGroup
#
#  This module defines the virtual concept of a gas group and is only used
#  for data logging for lumping gas flows for differenc controlers into a 
#  single data value based on flow values and on a control flag
#  (usually a relay). It is mainly used for cross-over systems where 
#  fast gas changes is desired and multiple gas lines with identical control
#  systems are switched after gas flows has stabilised.
#
#  To obtain a gas group instance use the constructor:
#
#  $id = RFC::GasGroup->new($name,$rig)
#
#  The class does not define any new functions
#
#  Note that the read and readstring functions only add the gas flows for 
#  the gasses where the flow is above the cutoff_report value defined in the 
#  configuration for that gas (Thus remember to set a sensible value for this
#  setting)!
# 
#  Similarly for the setpoint() function which only add the setpoints for the
#  gasses which are selected.
#
############################################################################

use strict;
use warnings;
use RFC::Header;
use RFC::BaseDevice;
use RFC::Cache;
our @ISA = qw(RFC::BaseDevice);

BEGIN {
    use Exporter ();
    our ($VERSION, @ISA, @EXPORT, @EXPORT_OK, %EXPORT_TAGS);
    $VERSION = 1.0;
    %EXPORT_TAGS = (
        'standard'=>[],
                    );
    Exporter::export_ok_tags('standard');
    Exporter::export_tags('standard');
    @ISA = qw(Exporter);
}

sub new()
{
    my $class = shift;
    my $self = $class->SUPER::new(@_);
    $self->{'_type'} = 'Gasgroup';
    $self->{'_mode'} = 'Readonly';
    $self->{'_setup_tags'} = ['gasses','title','show_plot','use_cache'];
    $self->{'_desc'} = {
	'gasses' => 'Names of gas devices included in gas group',
	'title' => 'Optional title',
	'use_cache'=>'Determines if persisten caching of read values is allowed',
    };    
    $self->{'_default'} = {
	'gasses' => '',
	'use_cache'=>'No',
    };
    $self->{'_values_mode'} = ['Readonly'];
    bless $self,$class;
    $self->{'_gas_devices'} = []; 
    $self->{'_section'} = 'gas_group_'.$self->name;
    return $self->init;
}


sub test()
{
    my $self = shift;
    foreach my $gas (@{$self->{'_gas_devices'}})
    {
        return 0 unless ($$gas{'id'}->test());
    }
    return 1;
}

sub Accept
{
    my $self = shift;
    my $visitor = shift;
    return undef if ($self->{'_seen_visitors'}{$visitor});
    foreach my $gas (@{$self->{'_gas_devices'}})
    {
        $$gas{'id'}->Accept($visitor);
        $$gas{'c_device'}->Accept($visitor);
    }
    $visitor->VisitComplex($self);
    $self->{'_seen_visitors'}{$visitor} = 1;
    return undef;
}

sub test_string()
{
    my $self = shift;
    my $data = RFC::Cache->new();
    my @arr = ('Gas group '.$self->name.': '.$self->{'_gasses'}.' Flow: '.$self->read($data));
    foreach my $gas (@{$self->{'_gas_devices'}})
    {
        my $flow = $$gas{'id'}->read_cutoff($data);
        my $cval = $$gas{'c_device'}->read($data);
        my $testval = $$gas{'c_val'};
        push @arr,$$gas{'name'}.": $flow, control_value: $testval, relay_read: $cval",
    }
    return join("\n",@arr);
}

sub setpoint()
{
    my $self = shift;
    my $total = 0;
    my $data = RFC::Cache->new();
    unless ($self->{'_gasses'})
    {
	return 0 
    }
    foreach my $gas (@{$self->{'_gas_devices'}})
    {
	my $flow = $$gas{'id'}->setpoint();
	my $cval = $$gas{'c_device'}->read($data);
	next unless ($cval == $$gas{'c_val'});
	$total += $flow;
    }
    return $total;
}

sub read_nocache()
{
    my $self = shift;
    my $res = undef;
    my $data = undef;
    if (@_)
    {
        $data = $_[0];
    }
    else
    {
	$data = RFC::Cache->new();
	$data->debug($self->debug()) if ($self->debug);
    }
    $self->check_cache($data);
    unless ($self->{'_gasses'})
    {
	$self->set_cache(0);
	$self->{'_last_read'} = Time::HiRes::time;
	return 0 
    }
    my $total = 0;
    foreach my $gas (@{$self->{'_gas_devices'}})
    {
	my $flow = $$gas{'id'}->read_cutoff($data);
	my $cval = $$gas{'c_device'}->read($data);
	next unless ($cval == $$gas{'c_val'});
	$total += $flow;
    }
    my $str = time .' '.$self->name.' '.$total;
    $self->rig->kanaldata($str) unless ($self->readstring_ignore);
    $self->set_cache($total);
    $self->{'_last_read'} = Time::HiRes::time;
    return $total;
}


sub readstring()
{
    my $self = shift;
    return undef if ($self->readstring_ignore);
    my $total = $self->read(@_);
    my @t = $self->get_time();
    my $t = join(':',@t);
    my $res = join(' ',$self->name,$t,time,sprintf("%.5f",$total));
    $self->writedebug($res) if ($self->debug > 1);
    return $res;
}


sub init()
{
    my $self = shift;
    foreach my $tag ($self->setup_tags())
    {
        $self->{'_'.$tag} = $self->get_default($tag);
        my $conf = $self->get_conf($tag);
        $self->{'_'.$tag} = $conf if (defined($conf) && $conf =~ /\w/);
    }
    unless ($self->{'_gasses'})
    {
	return $self 
    }
    my @list = ();
    foreach my $gas (split(/\s*\,\s*/,$self->{'_gasses'}))
    {
	my %h = ('name' => $gas);
	my $id = $self->rig->get_device('gas',$gas);
	$id = $self->rig->init_device('gas',$gas) unless ($id);
	unless ($id)
	{
	    $id = RFC::Device::new_GAS($self->rig,$gas);
	    $self->rig->register_gas($id);
	}
	$self->die("Could not get an id for gas $gas for rig ".$self->rig->name) unless ($id);
	$h{'id'} = $id;   
	$h{'c_device'} = $id->control_device();
	$h{'c_val'} = $id->control_value();
	$id->attatch_observer(\$self);
	push @list,\%h if ($id);
    }
    $self->{'_gas_devices'} = \@list;
    return $self;
}

sub print_config()
{
    my $self = shift;
    my @arr = ();
    push @arr,'Name: '.$self->name;
    push @arr,'Mode: '.$self->mode;
    my @list = ();
    foreach my $gas (@{$self->{'_gas_devices'}})
    {
	push @list,$$gas{'name'};
    }
    push @arr,'Gasses: '.join(', ',@list);
    return join (', ',@arr);
}

sub observe
{
    my $self = shift;
    $self->notify(@_);
}


return 1;
