package ProjectTools;
my $pkg_nm = 'ProjectTools';

# Provides tools for obtaining and working with the PROJECT variable, which
# determines the project / account number to use in job submission scripts
# and/or directory paths on some machines.

# Public routines:

# find_project()
#   Tries to find a project / account number to use

# check_project_required_but_unset(project, cfg_ref)
#   Checks if PROJECT is required for this machine, but has not been set

# set_project(project, cfg_ref)
#   Sets the PROJECT xml variable in cfg_ref

# Note that entities prefixed with an underscore (_) should be treated as
# private to this module, and are not meant to be accessed by other code.

use strict;
require ConfigCase;

# Note that this is variable should only be used internally to this module.
# External code that wants to check whether the PROJECT xml variable has been
# set should check against the default specified in config_definition.xml
# (currently "PROJECT_UNSET").
use constant _PROJECT_UNSET => "";

# ------------------------------------------------------------------------
# Public routines
# ------------------------------------------------------------------------

sub find_project
{
    # Tries to find a project/account number to use. If none can be found,
    # returns _PROJECT_UNSET.

   my $project = _PROJECT_UNSET;

   if (defined $ENV{'PROJECT'}) {
      $project = $ENV{'PROJECT'};
   }
   elsif (defined $ENV{'ACCOUNT'}) {
      $project = $ENV{'ACCOUNT'};
   }
   else {
      # Loop over possible files that can contain a project number.
      # (We should eventually remove .ccsm_proj, but it is kept now for
      # backwards compatibility.)
      my @proj_filenames = ($ENV{'HOME'} . "/.cesm_proj", 
                            $ENV{'HOME'} . "/.ccsm_proj");

      foreach my $proj_filename (@proj_filenames) {
         if (-f $proj_filename) {
            $project = _read_project_from_file($proj_filename);
            last if ($project ne _PROJECT_UNSET);
         }
      }
   }

   return $project;
}


sub check_project_required_but_unset
{
   # Checks if PROJECT is required for this machine, but has not been set

   my ($project, $cfg_ref) = @_;

   if (($project eq _PROJECT_UNSET) && ($cfg_ref->get('PROJECT_REQUIRED') eq "TRUE")) {
      die <<"EOF";
** ERROR **
   A project must be specified for this machine, in order to set paths and/or an
   account number in job submission scripts.

   You can specify a project number in one of the following ways:
   (1) via the -project argument to create_newcase
   (2) via the \$PROJECT or \$ACCOUNT environment variables
   (3) via a file named .cesm_proj in your home directory, whose first line gives a project number
EOF
   }

}


sub set_project
{
   # Sets the PROJECT xml variable in cfg_ref. However, if $project hasn't been
   # set, then this does NOT set the xml variable, instead keeping it at its
   # default value.

   my ($project, $cfg_ref) = @_;

   if ($project ne _PROJECT_UNSET) {
      $cfg_ref->set('PROJECT', "$project");
   }
}

# ------------------------------------------------------------------------
# Private routines
# ------------------------------------------------------------------------

sub _read_project_from_file 
{
   # Try to read a project number from a file with the given file name. Return
   # the project number if found. If we can't find a project number in that
   # file, return _PROJECT_UNSET.
   
   my ($proj_filename) = @_;
   
   my $project = _PROJECT_UNSET;

   # read first line
   open my $proj_file, '<', $proj_filename;
   my $firstline = <$proj_file>;
   close $proj_file;

   # check the first line for something that looks like a project number
   if ($firstline =~ /^\s*(\S+)/) {
      $project = $1;
   } else {
      print "WARNING: $proj_filename found, but I cannot find a project number on its first line\n";
   }

   return $project;
}
   


