#!/usr/bin/perl
use strict;
use English;
use File::Copy;
use File::Path;
use File::Find;
use File::Basename;
use File::Spec::Functions;
use Term::ANSIColor;
use POSIX qw(tmpnam);
use Cwd;
use Cwd 'abs_path';

BEGIN {
  # Add the directory of this file to the search path
  push @INC, dirname($PROGRAM_NAME);
  my $scriptdir = abs_path(dirname($PROGRAM_NAME));
  my $gridhome = `$scriptdir/../../srvm/admin/getcrshome`;
  my $incdir = "$gridhome/crs/install";
  push @INC, $incdir;
}

use crsconfig_lib;
use s_crsconfig_lib;

# globals
my $DEBUG;

#cmd line params
my $srchome = $ARGV[0];
my $dsthome = $ARGV[1];

# MAIN SCRIPT BODY
#

# pull all parameters defined in crsconfig_params and s_crsconfig_defs (if
# it exists) as variables in Perl
my $paramfile = catfile($dsthome, "crs", "install", "crsconfig_params");

# pull all parameters defined in crsconfig_addparams
my $addfile = catfile($dsthome, "crs", "install", "crsconfig_addparams");

# pull all definitions in s_crsconfig_defs (if it exists) as variables in Perl
# this file might not exist for all platforms
my $osdfile = catfile($dsthome, "crs", "install", "s_crsconfig_defs");

if (!$DEBUG) { $DEBUG = $ENV{'ORA_INSTALL_DEBUG'}; }

### Set this host name (lower case and no domain name)
our $HOST = tolower_host();
our $SUPERUSER = check_SuperUser ();

# subsequent processing 
my $cfg =
  crsconfig_lib->new(IS_SIHA             => FALSE,
                     paramfile           => $paramfile,
                     osdfile             => $osdfile,
                     addfile             => $addfile,
                     crscfg_trace        => TRUE,
                     DEBUG               => $DEBUG,
                     HAS_USER            => $SUPERUSER,
                     HOST                => $HOST,
                     );



copyConfigurationData($srchome, $dsthome);
trace("Preparing the destination GI home for out-of-place patching ...");
preunlockPatchDestHome($dsthome);

sub copyConfigurationData
{
   my $srcHome = $_[0];
  my $dstHome = $_[1];

  trace("Source home: $srcHome; Destination home: $dstHome");
  if ($srcHome ne $dstHome)
  {
    trace("Copying parameter files from src home to dst home ...");
    my $envtxt = 's_crsconfig_' . $CFG->HOST . '_env.txt';
    my @paramfiles = ('crsconfig_params',
                      's_crsconfig_defs',
                      $envtxt);

    foreach my $file (@paramfiles)
    {
      my $srcParaFile =
          catfile($srcHome, 'crs', 'install', $file);
      my $dstParaFile =
          catfile($dstHome, 'crs', 'install', $file);

      if (-e $srcParaFile)
      {
        my $needCopy = 0;

        if (! -e $dstParaFile)
        {
          trace("Copy needed as $dstParaFile is not present");
          $needCopy = 1;
        }
        elsif (! compareFiles($srcParaFile, $dstParaFile))
        {
          trace("Copy needed as $dstParaFile is different from $srcParaFile");
          $needCopy = 1;
          my $dstParaFileBak = $dstParaFile . '.oop-patching';
          copy_file($dstParaFile, $dstParaFileBak);
        }
       
        if (1 == $needCopy)
        {
          trace("Copying the parameter file $file ...");
          copy_file($srcParaFile, $dstParaFile);
        }
      }
    }


    trace("Copying GPnP files from src home to dst home ...");
    copy_gpnpfiles($srcHome, $dstHome);

    trace("Copying configuration files/dirs from src home to dst home ...");
    copyfiles($srcHome, $dstHome);

    my $cdataDir = catfile($dstHome, 'cdata');
    my $olrPath = ($CFG->IS_SIHA) ? catfile($cdataDir, 'localhost') : $cdataDir;
    my $dstolrfile = catfile($olrPath,  $CFG->HOST . '.olr');
    my $srcolrfile = s_get_olr_file("olrconfig_loc");

    trace("Source OLR: $srcolrfile; Destination OLR: $dstolrfile");
    if ($srcolrfile ne $dstolrfile)
    {
      trace("Copying OLR data file from src to dst ...");
      copy_file($srcolrfile, $dstolrfile);
    }
  }
}

sub compareFiles
{
  my $file1 = $_[0];
  my $file2 = $_[1];
  my $rt = FALSE;

  trace("Comparing two files by content:  $file1 and $file2");

  unless (open(FILE1, "<$file1"))
  {
    trace("Could not open file $file1 for reading (error: $!)");
    return $rt;
  }

  unless (open(FILE2, "<$file2"))
  {
    trace("Could not open file $file2 for reading (error: $!)");
    return $rt;
  }

  my $file1Cnt = join("", <FILE1>);
  my $file2Cnt = join("", <FILE2>);

  close(FILE1);
  close(FILE2);

  if ($file1Cnt eq $file2Cnt)
  {
    trace("Two files have identical contents");
    $rt = TRUE;
  }
  else
  {
    trace("Two files have different contents");
  }

  return $rt;
}

sub preunlockPatchDestHome
{
   my $unlock_home = $_[0];

   trace("prepare for unlock: $unlock_home");

   modifyparamfile("ORACLE_HOME", $unlock_home);
   modifyparamfile("CRFHOME", $unlock_home);
   modifyparamfile("JREDIR", "$unlock_home/jdk/jre/");
   modifyparamfile("JLIBDIR", "$unlock_home/jlib");

   # set new home instantiate prior to unlock
   $ENV{'ORACLE_HOME'} = $unlock_home;
   $CFG->ORA_CRS_HOME($unlock_home);

   # instantiate prior to unlock
   instantiate_scripts($unlock_home);
   my $cdataDir = catfile($unlock_home, 'cdata');
   my $olrPath = $cdataDir;
   $CFG->OLR_LOCATION(catfile($olrPath,  $CFG->HOST . '.olr'));
   add_localOlr_OlrConfig_OcrConfig();

   my @crsconfig_dirs = read_file(catfile($CFG->ORA_CRS_HOME,
                        'crs', 'utl', 'crsconfig_dirs'));
   create_dirs(\@crsconfig_dirs);

   copy_wrapper_scripts();
   my @crsconfig_fileperms = read_file(catfile($CFG->ORA_CRS_HOME,
                             'crs', 'utl', 'crsconfig_fileperms'));
   set_file_perms(\@crsconfig_fileperms);

}

sub copy_gpnpfiles
{
   my $sourcedir = $_[0];
   my $destdir   = $_[1];

   copy_gpnpglobalfiles($sourcedir, $destdir);
   copy_gpnpnodefiles($sourcedir, $destdir);
}

sub copy_gpnpglobalfiles
{
   my $sourcedir = $_[0];
   my $destdir   = $_[1];

   copydir(catdir($sourcedir,'gpnp','profiles'), catdir($destdir,'gpnp','profiles'));
   copydir(catdir($sourcedir,'gpnp','wallets'), catdir($destdir,'gpnp','wallets'));
}

sub copy_gpnpnodefiles
{
   my $sourcedir = $_[0];
   my $destdir   = $_[1];
   my $host = tolower_host();

   copydir(catdir($sourcedir,'gpnp',$host), catdir($destdir,'gpnp',$host));
}

sub copydir
{
   my $sourcedir = $_[0];
   my $destdir   = $_[1];
   my ($filepath, $filename, $destfilepath, $dirpath);
   my @filelist;
   trace("source dir=$sourcedir");
   trace("dest   dir=$destdir");

   find(sub { push @filelist, $File::Find::name }, $sourcedir);

   if ($CFG->platform_family eq "windows") {
      # escape char '\' on Windows
      $destdir =~ s!\\!\\\\!g;
      $sourcedir =~ s!\\!\\\\\\\\!g;
   }

   foreach $filepath (@filelist) {
     if ( -f $filepath) {
        $filename = basename($filepath);
        # Do not copy OCR backup files
        if ($filename =~ /\.ocr$/)
        {
          trace("Skipping the file '$filename'");
          next;
        }

        $dirpath = dirname($filepath);

        if ($CFG->platform_family eq "windows") {
           # escape char '\' on Windows
           $dirpath =~ s!\\!\\\\!g;
        }

        $dirpath =~ s/$sourcedir/$destdir/g;

        if (! -e $dirpath) {
          trace("creating directory $dirpath");
           mkpath( $dirpath);
           s_set_ownergroup($ORACLE_OWNER, $ORA_DBA_GROUP, $dirpath);
        }

        $destfilepath = catfile($dirpath, $filename);
        trace ("copying file=$filename");
        trace ("source file path=$filepath");
        trace ("dest file path=$destfilepath");
        copy_file($filepath, $destfilepath,$ORACLE_OWNER, $ORA_DBA_GROUP);
        }
   }
}

sub copyfiles
{
   my $sourcedir = $_[0];
   my $destdir   = $_[1];
   my $host = tolower_host();

   #copy gpnp, network/admin/, cdata and opmn/conf files
   if (! $CFG->IS_SIHA) {
      copy_gpnpglobalfiles($sourcedir, $destdir);
      copydir(catdir($sourcedir,'network','admin'), catdir($destdir,'network','admin'));
      copydir(catdir($sourcedir,'cdata'), catdir($destdir,'cdata'));

      # for opmn/conf, we only need to copy ons.config file
      my $sourcefile = catfile ($sourcedir, 'opmn', 'conf', 'ons.config');
      my $destfile   = catfile ($destdir, 'opmn', 'conf', 'ons.config');
      copy_file($sourcefile, $destfile, $ORACLE_OWNER, $ORA_DBA_GROUP);
   }
   else {
      copydir(catdir($sourcedir,'network','admin'), catdir($destdir,'network','admin'));
   }
}

sub modifyparamfile
{

   my $param = $_[0];
   my $paramval = $_[1];

   trace("modify $param $CFG->paramfile");

   my $params_file = $CFG->paramfile;
   my @params_table = read_file ($params_file);
   my $updateParamsFile = FALSE;
   my $ix = 0;

   foreach my $rec (@params_table) {
      chomp($rec);
      if ($rec =~ m/^$param=/) {
         my ($key, $value) = split (/=/, $rec);
         $params_table[$ix] = $param . "=" . "$paramval";
         $updateParamsFile = TRUE;
         last;
      }

      $ix++;
   }
   if ($updateParamsFile) {
      # save original params file
      my $save_file = catfile (dirname($params_file), 'crsconfig_params.saved');
      copy_file ($params_file, $save_file);

      # delete old file and create new file
      if (s_remove_file($params_file)) {
         open (SFILE, ">$params_file")
            || die ("Can't open $params_file to write: $!");

         foreach my $rec (@params_table) {
            chomp($rec);
            print SFILE "$rec\n";
         }

         close SFILE;
      }
   }
}


