=head1 NAME

  CFX5::Parallel::Reqs::mpsmpi_script - MSMPI script generator for CFX parallel

$Id$

=cut

package CFX5::Parallel::Reqs::msmpi_script;

use CFX5::Parallel::Reqs::Base;
push @ISA, qw(CFX5::Parallel::Reqs::Base);

use CFX5::Output qw(:all);
use CFX5::FileOps qw(append_to_file);

use strict;

sub setup {
  my $self = shift;
  my $workdir = shift;

  my $ppe = $self->ppe();
  my $config = $ppe->config_object();
  my $master_host = $ppe->master_host();
  my $sm = $ppe->start_method();

  # fill in shared parts of the header
  my $header = $sm->appfile_header();
  if (defined $header)
  {
    $header = $sm->fill_shared_template($header, $ppe);
  }

  # fill in shared parts of the host entry
  my $host_entry = $sm->appfile_host_entry();
  $host_entry = $sm->fill_shared_template($host_entry, $ppe);

  # Parse CCP_NODES: <nhost> <host1> [n1] <host2> [n2] ... <hostn> [nn]
  # Create required list of hosts and counts
  my $proc_per_solver = $ENV{_CFX_PROC_PER_SOLVER};
  my ($nhost,@hostncs_raw) = split(' ', $ENV{CCP_NODES});

  my @hostncs;
  while (my $hostname = shift @hostncs_raw)
  {
    last unless (my $hostcount = shift @hostncs_raw);
    $hostcount /= $proc_per_solver if (defined $proc_per_solver);
    push @hostncs, $hostname, $hostcount;
  }
  my $hostncs_list = join ' ', @hostncs;

  # Loop over hosts and assemble host entries
  my @host_entries;
  my $header_complete = 0;
  for (my $ihost=0; $ihost<$nhost; $ihost++)
  {
    my ($hostname, $hostcount) = splice @hostncs, 0, 2;
    my $host = new CFX5::Parallel::Host($config, $hostname);
    $host->architecture($master_host->architecture());

    # Assemble the header. For multiple hosts, fill host template values
    # using the first remote host to ensure UNC paths are used.
    # All hosts use a common installation on a Windows HPC cluster.
    unless ($header_complete or $ppe->is_master($host) and $nhost>1)
    {
      if (defined $header) {
        $header = $sm->fill_host_template($header, $ppe, 1, $host, 1);
        $header_complete = 1;
      }
    }
    
    my $entry = $sm->fill_host_template($host_entry, $ppe, $hostcount,$host, 0);
    $sm->assert_fully_replaced($entry);
    push @host_entries, $entry;
  }

  # Check header and prefix with @ to disable echoing
  if (defined $header)
  {
    $sm->assert_fully_replaced($header) or return undef;
    $header = '@'.$header;
  }
  else
  {
    $header = '@';
  }
  my $contents = join(' ', $header, join(' : ', @host_entries));

  # Command too long: Use -hosts specification with shared working directory
  my $cmdlen = length($contents);
  if ($cmdlen > 8192)
  {
    printf "Using shared working directory to respect command length limit.\n";
    $host_entry =~ s/-host\s+\S+\s+-np\s+\S+/-hosts $nhost $hostncs_list/;
    my $entry = $sm->fill_host_template($host_entry, $ppe, 1, $master_host, 1);
    $contents = join(' ', $header, $entry);
  }

  # Write file (remove any existing file first)
  my $filename = 'msmpi_script.bat';
  $workdir->remove_file($filename) if $workdir->have_file($filename);
  my $file = $workdir->creatable_file($filename);
  unless (append_to_file($file, "$contents\n")) {
    _error("Error writing $filename: $!");
    return undef;
  }

  $self->{__PACKAGE__ . '::filename'}=$file;
}

sub get_replacement_text {
  my $self=shift;
  $self->{__PACKAGE__ . '::filename'};
}

1;
