=head1 NAME

  CFX5::Simulation::Configuration::Remeshing::Remesh - Low level remesh object definition

=head1 SYNOPSIS

This object is used by L<CFX5::Simulation::Configuration::Remeshing>, to manage individual 
REMESH objects defined in the CCL.

=head1 DESCRIPTION

$Id$

=cut

package CFX5::Simulation::Configuration::Remeshing::Remesh;

use strict;

use CFX5::Output qw(:all error_text);
use CFX5::PathManip qw(dirname basename fullpath join_file split_mult_files normalize_filename);
use CFX5::CCLI;
use CFX5::PkgLoader qw(cfx5_require);


#
################################################################################
# new: Constructor
################################################################################
#
sub new {
  my $this = shift;
  my %params = @_;
  
  my $class = ref($this) || $this;
  my $self = { 
    Name     => $params{"Name"}, 
    Option   => $params{"Option"}, 
    CCLPath  => $params{"CCLPath"},
    ActCond  => undef,
    CCLAPI   => $params{"CCLAPI"}, 
    RunDir   => $params{"RunDir"},
    MeshFile => undef,
    ResFile  => undef,
    OutObj   => $params{"OutObj"},
    Parent   => $params{"Parent"}, 
    RemeshOutFile     => undef,
    MeshReloadOptions => $params{"MeshReloadOptions"},
	};
  bless $self, $class;
  return $self;
}

#
################################################################################
# General Data Access Routines
################################################################################
#
#=======================================================================
# Get
#=======================================================================
#
sub Get {
  my $self    = shift ;
  my $setting = shift ;
#
#-----------------------------------------------------------------------
# Member Data
#-----------------------------------------------------------------------
#  
  # Return data that needs dereferencing
  if ($setting eq "CCLAPI" or 
      $setting eq "RunDir" or
      $setting eq "OutObj" ) {
    return ${$self->{$setting}} ;
  }

  # General Returns
  if (defined $self->{$setting}) {
    return $self->{$setting} ; 
  }
#
#-----------------------------------------------------------------------
# CCL Data
#-----------------------------------------------------------------------
#  
  my $CCLPath = $self->SettingToCCL($setting);
  if (defined $CCLPath) { 
    my $cclapi = $self->Get("CCLAPI") ;
    if (!defined $cclapi) {
      _error "Get: Could not connect to CCL." ;
    }
    my $retVal; 
    $cclapi->getStringValue($CCLPath,\$retVal) ;
    if (defined $retVal) {
      return $retVal; 
    }
  }
#
#-----------------------------------------------------------------------
# Unhandled Data
#-----------------------------------------------------------------------
#  
  return undef ; 
}

#
#=======================================================================
# Set
#=======================================================================
#
sub Set {
  my $self    = shift ;
  my $setting = shift ;
  my $value   = shift ;
  
  $self->{$setting} = $value ; 
  
  1; 
}

#
#=======================================================================
# SettingToCCL
#=======================================================================
#
# This routine provides a mapping between a particular setting and
# some CCL
#
sub SettingToCCL {
  my $self = shift ; 
  my $setting = shift; 
  
  my $CCLPath = $self->Get("CCLPath") ; 
  
  my %CCL = (
    "Location"         => $CCLPath."/Location", 
    "Geometry File"    => $CCLPath."/Geometry File", 
    "Mesh Replay File" => $CCLPath."/Mesh Replay File", 
    "Replacement Mesh File" => $CCLPath."/Replacement Mesh File", 
  ); 
  
  return $CCL{$setting};
}

#
################################################################################
# Print Object Data
################################################################################
#
sub PrintData {
  my $self=shift;
  
  my $key; 
  my $val; 
  print "\n--- Printing Contents for Remesh Object ---\n" ;
  while (($key,$val)=each %{$self}) {
    print "$key\t= $val\n"
  }
  print "-------------------------------------------\n" ;
  1; 
}

#
################################################################################
# IsActive
################################################################################
#
sub IsActive {
  my $self=shift; 
  my $pCondNames = shift; 
  my $pCondTypes = shift; 
#
  my @solTermCondNames = @$pCondNames; 
  my @solTermCondTypes = @$pCondTypes; 
#
  my %count     = () ;
  my @actCond   = () ; 
  my @inactCond = () ; 
#
#-----------------------------------------------------------------------
# First Pass - See if any of the solver termination conditions do not
# allow remeshing (e.g. most solver-internal conditions)
#-----------------------------------------------------------------------
#
  for (my $ii=0; $ii<scalar(@solTermCondNames); $ii++) {
    # Type 1 is solver internal, type 2 is user defined
    if ($solTermCondTypes[$ii] eq '1' and 
        $solTermCondNames[$ii] ne 'The mesh is invalid or folded' ) {  
      return @actCond ; 
    }
  }
#
#-----------------------------------------------------------------------
# Now loop over remesh object activation conditions and see if any 
# are satisfied by the reported solver termination conditions
#-----------------------------------------------------------------------
#
  # Connect to the CCL
  my $cclapi=$self->Get("CCLAPI") ;
  if (!defined $cclapi) {
    _error "IsActive: Could not connect to CCL" ;
    return @actCond ; 
  }
#
  my $condNameList ; 
  $cclapi->getStringValue($self->Get("CCLPath")."/Activation Condition List",
                          \$condNameList) ;
  my @condNames = split_mult_files($condNameList) ;
  push(@condNames,"The mesh is invalid or folded");
  #
  # Look for intersection between control condition entries and 
  # solver termination conditions
  # --> first loop counts occurrances of each entry in union of activation and
  #     realised solver termination conditions
  # --> second loop creates list of conditions with count greater than 1
  #
  my $cond ;
  foreach $cond (@condNames,@solTermCondNames) {$count{$cond}++}
  foreach $cond (keys %count) {
    push(@{$count{$cond} > 1 ? \@actCond : \@inactCond}, $cond);
  }
 
  $self->Set("ActCond",undef) ; 

  if (@actCond) {
    $self->Set("ActCond",join(', ',@actCond)) ; 
  }
  return @actCond ; 
}

#
################################################################################
# End of Package
################################################################################
#

1 ;
