#!/usr/bin/env perl

use FindBin;
use lib ($FindBin::Bin . "/chplenv");
use Run qw(ret run);
use warnings;

# We put all the printing in a subroutine so that
# it can be redone for --make where we want to also
# print all the configuration in the object directory
# name.
sub go {
  @ARGS=@_;

  # $mode can be list, make, compiler, runtime, launcher, or shell
  $first = 1;
  $mode = "list";
  if( defined $ARGS[0] ) {
    $mode = $ARGS[0];
    $mode =~ s/^-+//;
  }

  if( $mode eq "list" or
      $mode eq "make" or
      $mode eq "compiler" or
      $mode eq "runtime" or
      $mode eq "launcher" ) {
    # OK!
  } elsif( $mode eq "sh" or
           $mode eq "csh" ) {
    # OK!
    $shell = $mode;
    $mode = "shell";
  } elsif( $mode =~ /help/ or $mode eq "h" ) {
    print "Usage: $0 [--list|--make|--compiler|--runtime|--launcher|--sh|--csh\n";
    print "       --compiler - print out path component for compiler objects\n";
    print "       --runtime - print out path component for runtime objects\n";
    print "       --launcher - print out path component for launcher objects\n";
    print "       --sh - print out a sh/bash script to reproduce the environment\n";
    print "       --csh - print out a csh/tcsh script to reproduce the environment\n";
    exit(0);
  } else {
    die "Unknown mode $mode";
  }

  $uname = `uname -a`;

  print "uname -a: $uname" if $mode eq "list";

  $CHPL_HOME="";
  if( defined $ENV{'CHPL_HOME'} ) {
    $CHPL_HOME = $ENV{'CHPL_HOME'};
  }

  if( $mode eq "list" ) {
    print "CHPL_HOME: $CHPL_HOME\n";
    print "script location: $FindBin::Bin\n";
  # For shells, we don't print out CHPL_HOME if it is
  # the empty string, which isn't a useful setting
  # for that environment variable anyway...
  } elsif ( $mode eq "shell" and $CHPL_HOME ne "" ) {
    print_setenv("CHPL_HOME", $CHPL_HOME);
  }

  $hostplatform = run("platform", "--host", "1");
  $hostcompiler = run("compiler", "--host");

  if( $mode eq "runtime" ) {
    # Don't print host platform/compiler for runtime
  } else {
    printit("CHPL_HOST_PLATFORM", "", $hostplatform);
    printit("CHPL_HOST_COMPILER", "", $hostcompiler);
  }

  $targplatform = run("platform", "--target");
  $targcompiler = run("compiler", "--target");

  if( $mode eq "compiler" or $mode eq "launcher" ) {
    # Don't print target platform/compiler for compiler/launcher
  } else {
    printit("CHPL_TARGET_PLATFORM", "", $targplatform);
    printit("CHPL_TARGET_COMPILER", "", $targcompiler);
  }

  if ( $mode eq "compiler" ) {
      # Don't print locale model for compiler
  } else {
      $localeModel = run("localeModel");
      printit("CHPL_LOCALE_MODEL", "loc", $localeModel);
  }

  $comm = run("comm");
  printit("CHPL_COMM", "comm", $comm, "!compiler");
  if ( $mode ne "make" and ($comm eq "none" || $comm eq "ugni") ) {
  } else {
    $commsubstrate = run("commSubstrate");
    printit("  CHPL_COMM_SUBSTRATE", "", $commsubstrate, "runtime,launcher");
    if ( $mode eq "make" or $comm eq "gasnet") {
      $commsegment = run("commSegment");
      printit("  CHPL_GASNET_SEGMENT", "", $commsegment, "runtime,launcher");
    }
  }

  $tasks = run("tasks");
  printit("CHPL_TASKS", "tasks", $tasks, "runtime,launcher");
  if( $mode eq "make" ) {
    $threads = run("threads");
    printit("CHPL_THREADS", "threads", $threads);
  }
  $launcher = run("launcher");
  printit("CHPL_LAUNCHER", "launch", $launcher, "launcher");
  $timer = run("timers");
  printit("CHPL_TIMERS", "tmr", $timer, "runtime,launcher");
  if( $mode eq "make" ) {
    $hostmem = run("mem", "--host");
    $tgtmem = run("mem", "--target");
    printit("CHPL_HOST_MEM", "hostmem", $hostmem, "runtime,launcher");
    printit("CHPL_TARGET_MEM", "tgtmem", $tgtmem, "runtime,launcher");
  } else {
    $mem = run("mem");
    printit("CHPL_MEM", "mem", $mem, "runtime,launcher");
  }
  $make = run("chplmake");
  if( $mode eq "list" or
      $mode eq "make" or
      $mode eq "shell" ) {
    printit("CHPL_MAKE", "make", $make);
  }
  $atomics = run("atomics");
  printit("CHPL_ATOMICS", "atomics", $atomics, "runtime,launcher");
  if ($comm eq "none") {
  } else {
    $network_atomics = run("atomics", "--network");
    printit("  CHPL_NETWORK_ATOMICS", "", $network_atomics, "runtime,launcher");
  }
  $gmp = run("gmp");
  printit("CHPL_GMP", "gmp", $gmp, "runtime");
  $hwloc = run("hwloc");
  printit("CHPL_HWLOC", "hwloc", $hwloc, "runtime");
  $regexp = run("regexp");
  printit("CHPL_REGEXP", "re", $regexp, "runtime");
  $wide_ptrs = run("widePointers");
  printit("CHPL_WIDE_POINTERS", "wide", $wide_ptrs);
  if( $mode eq "make" ) {
    $wide_ptrs_def = run("widePointers", "--define");
    printit("CHPL_WIDE_POINTERS_DEFINES", "widedef", $wide_ptrs_def);
  }
  $llvm = run("llvm");
  printit("CHPL_LLVM", "llvm", $llvm, "compiler");
  $aux_fs = run("auxFilesys");
  printit("CHPL_AUX_FILESYS", "fs", $aux_fs, "runtime");

  if( $mode eq "make" ) {
    print "CHPL_MAKE_COMPILER_SUBDIR=";
    go("--compiler");
    print "CHPL_MAKE_RUNTIME_SUBDIR=";
    go("--runtime");
    print "CHPL_MAKE_LAUNCHER_SUBDIR=";
    go("--launcher");
  } elsif( $mode eq "compiler" or
           $mode eq "runtime" or
           $mode eq "launcher" ) {
    print "\n";
  }


}

go(@ARGV);

sub printit {
  # first argument - the environment variable name
  # which might include some spaces for pretty padding 
  # e.g. CHPL_REGEXP or CHPL_TASKS
  my $envname = shift;
  # second argument - a short name for the variable when
  # printing out a configuration path component. In many cases
  # it can be left blank.
  # e.g. re or tasks
  my $shortname = shift;
  # third argument - the value we have configured
  # e.g. re2 or fifo 
  my $value = shift;
  # fourth argument - when printing out a configuration path
  # component, should this configuration end up in launcher,
  # runtime, or compiler?
  # Leave it as "" or not passed for all modes,
  # setting it to "compiler" would mean only for compiler
  # setting it to "launcher,runtime" would mean either of those modes
  my $modeonly = shift;

  $modeonly = "" if not defined $modeonly;

  if( $mode eq "list" ) {
    print "$envname: $value\n";
  } elsif( $mode eq "make" ) {
    my $makename = $envname;
    $makename =~ s/^\s+//;
    $makename =~ s/^CHPL_/CHPL_MAKE_/;
    print "$makename=$value\n";
  } elsif( $mode eq "compiler" or
           $mode eq "runtime" or
           $mode eq "launcher" ) {
    my @modes = split(/,/, $modeonly);
    my $modematch = 0;
    if( $modeonly eq "" ) {
      $modematch = 1;
    } else {
      for my $m (split(/,/, $modeonly)) {
        if ($m eq $mode) {
          $modematch = 1;
        }
      }
    }
    if( not $modematch ) {
      # print nothing.
    } else {
      print "." if $first != 1;
      # if value begins with shortname,
      # just print value.
      if( $shortname eq "" or
          $shortname eq substr($value, 0, length($shortname)) ) {
        print "$value";
      } else {
        print "$shortname-$value";
      }
      $first = 0;
    }
  } elsif( $mode eq "shell" ) {
    print_setenv($envname, $value);
  } else {
    die "Unknown mode $mode";
  }
}


sub print_setenv {
  # first argument - the environment variable name
  my $env_name = shift;
  # second argument - the value for the variable
  my $env_val = shift;
  if( $shell eq "sh" ) {
    print "export $env_name='$env_val'\n";
  } elsif( $shell eq "csh" ) {
    print "setenv $env_name '$env_val'\n";
  } else {
    die "Unknown shell $shell";
  }
}
