#!/bin/sh

# takes dotnethome as param         -d
# takes network ip as param         -i
# takes installpath as param        -p
# takes installation key as param   -k
# takes install mode as param       -m
# takes verbose as param            -v
# takes password as param           -P
# takes force as param              -F
# takes auto start cache as param   -s

#--------------------------------------------------------------------------------------
echo ""
echo "======================================================"
echo "NCache Open Source (.NET Edition) Installation Script"
echo "======================================================"
echo ""

ISCONTAINER=false

PRODUCT="NCache"
PRODUCT_TAR="ncache-oss-install.tar.gz"
DOTNETPATH=
IP=
NCUSER="ncache"
DESTINATION="/opt"
LUCENE_DIST_MAP_PATH="/usr/share/ncache"
VERBOSE=
FORCE=
PASSWORD="ncache"
AUTO_START="yes"
INSTALLMODE="0"
CACHE_NAME="defaultCache"
INSTALLATIONTYPE="server"
INSTALLTYPE="op"
ENV="on-prem"
FIRST_NAME=
LAST_NAME=
COMPANY_NAME=
EMAIL=
KEY=
ENABLE_DUMP="false"
ONPREMHOST="https://app.alachisoft.com"
CLOUDHOST="https://cloud.alachisoft.com"
KEYVALID="false"
eval mac1=
eval mac2=
eval mac3=
eval mac4=

ncv="NC-OSS-5.3.6-64"

#--- .NET version(s) supported for NCache  (Minimum required version = 8.0)
DOTNETCOREVER="8.0"
VERIFIED="0"

#--------------------------------------------------------------------------------------
# ================================== FUNCTIONS ========================================
#--------------------------------------------------------------------------------------
printMessage ()
{
	message=$1
	echo "$message"
}
#--------------------------------------------------------------------------------------
printError ()
{
	message=$1
	echo "------"
	echo "ERROR: $message" 1>&2;
	echo ""
}
#--------------------------------------------------------------------------------------
printMode ()
{
	message=$1
	if [ ! -z "$VERBOSE" ]
	then
		echo "$message"
	fi
}

#--------------------------------------------------------------------------------------
usage ()
{
	printMessage "This script installs $PRODUCT and then configures it"
	printMessage "Providing optional arguments will override default implementation"
	printMessage ""
	printMessage "Usage: install [OPTION] ARG [OPTION] ARG ..."
	printMessage ""
	printMessage "  -k, --installkey        Installation key provided by alachisoft.com"
	printMessage "  -p, --installpath       If not provided then /opt/ncache will be used."
	printMessage "  -s, --startcache        To disable auto start of default cache on installation (-s no)"
	printMessage "  -i, --ipaddress         IP address to be used by $PRODUCT, if not provided then it will use the first IP found."
	printMessage "  -F, --force             Force create destination directory if provided directory does not exist."
	printMessage "  -P, --password          Provide password for user '$NCUSER', if user already exists then it will override its password."
	printMessage "  -t, --enableptrace      Allows users to take memory dumps of processes running under their ownerships. (default is false)"
	printMessage ""
	printMessage "By default this script will install $PRODUCT in the following directory /opt/ncache/, using first found ip-address."
	printMessage ""
	printMessage "Please contact support@alachisoft.com for any technical help."
	printMessage "For complete documentation visit the website https://www.alachisoft.com/resources/docs/"
	printMessage ""
	exit 1
}

GetMacAddresses()
{
i=1
D='/sys/class/net'
for nic in $( ls $D )
do
    if  grep -q up $D/$nic/operstate
    then
		eval mac$i=$(cat $D/$nic/address)
		if [ $i -eq 4 ]
		then
			break
		fi
		i=$((i+1))
    fi
done
}

PostInstallationActivity ()
{

NumberOfCPU="$(grep processor /proc/cpuinfo | wc -l)"
NumberofCores="$(nproc --all)"
NumberOfVCPU="$(grep processor /proc/cpuinfo | wc -l)"

Ram="$(cat /proc/meminfo | grep MemTotal | grep -o -E '[0-9]+')"
Ram=$((Ram/(1024*1024)))

OSCode="`uname`"
macName="`hostname`"
case $OSCode in
  'Linux')
    OSCode='12'
    ;;
  *)
	OSCode="-1"
	;;
esac

case $INSTALLMODE in
  '0')
    edt='server'
    ;;
   '2')
    edt='dev'
    ;;
  '3')
    edt='client'
    ;;
esac

GetMacAddresses
mi=$OSCode":"$NumberOfCPU":"$NumberofCores":"$NumberOfVCPU":"$Ram

curl --silent --output /dev/null --data "fn=$FIRST_NAME&ln=$LAST_NAME&email=$EMAIL&company=$COMPANY_NAME&ncv=$ncv&edt=$edt&netv=$versionFound&mi=$mi&ip=$ip&macName=$macName&mac1=$mac1&mac2=$mac2&mac3=$mac3&mac4=$mac4&env=$ENV" $ONPREMHOST/ncache/nc-getting-started.php &
}

#---------------------------------------------------------------------------------------------
#------------------ Verify whether the environment is docker or not --------------------------
ENVDOTNETCONTAINER=$(printenv DOTNET_RUNNING_IN_CONTAINER)

if [ ! -z "$ENVDOTNETCONTAINER" ] ; then
        if [ $ENVDOTNETCONTAINER ] ; then
                ISCONTAINER=true
        fi
fi

#---------------------------------------------------------------------------------------------
#------------------ Verify required version installation of pre requisites -------------------
verify()
{
	REQUIRED_VERSION=`echo $1 | sed -e 's;\.;;g'`
	FOUND_VERSION=`echo $2 | sed -e 's;\.;;g'`
	
	if [ $FOUND_VERSION -ge $REQUIRED_VERSION ]
	then
		VERIFIED="1"
	else
		VERIFIED="0"
	fi
}


#--------------------------------------------------------------------------------------
#--- Start of execution
#--------------------------------------------------------------------------------------

while [ "$1" != "" ]; do
    case $1 in
	-d | --dotnethome )	shift
			DOTNETPATH=$1
			;;
	
	-i | --ipaddress )	shift
			IP=$1
			;;

	-p | --installpath )	shift
			DESTINATION=$1
			;;	

	-k | --installkey )	shift
			KEY=$1
			;;
			
	-m | --installmode )	shift
			INSTALLMODE=$(echo "$1" | tr '[:upper:]' '[:lower:]')
			if [ $INSTALLMODE = "client" ] || [ $INSTALLMODE = "3" ] ; then
				INSTALLATIONTYPE="client"
				CACHE_NAME="defaultLocalCache"
				INSTALLMODE="3";
			elif [ $INSTALLMODE = "dev" ] || [ $INSTALLMODE = "2" ] ; then
				INSTALLATIONTYPE="dev"
				CACHE_NAME="defaultLocalCache"
				INSTALLMODE="2";
			else
				INSTALLATIONTYPE="server"
				CACHE_NAME="defaultCache"
				INSTALLMODE="0";
			fi
			;;
			
	-P | --password )	shift
			PASSWORD=$1
			NEWPASS="true"
			;;
			
	--onpremhost )	shift
			ONPREMHOST=$1
			;;
			
	--cloudhost )	shift
			CLOUDHOST=$1
			;;

	-s | --startcache ) shift
			AUTO_START=$1
			;;

	-t | --enableptrace ) shift
			ENABLE_DUMP=$1
			;;
			
	-F | --force )
			FORCE="true"
			;;
			
	-v | --verbose )
			VERBOSE="true"
			;;

	-h | --help )
			usage
			exit
			;;
	* )
			usage
			exit 1
    esac
    shift
done

printMessage "Executing script from user: $USER"

#--------------------------------------------------------------------------------------
# Ensure that NCache is not already installed
if [  -f "/usr/lib/ncinfo.xml" ]; then 
	echo ""
	printError "Either NCache is already installed or wasn't uninstalled properly."
	exit 1
fi
#--------------------------------------------------------------------------------------
# Make sure only root user can run our script
if [ "$(id -u)" != "0"  ] ; then
   printError "Installation requires root privileges."
   exit 1
fi

if [ ! -d $DESTINATION ] ; then
	if [ ! -z $FORCE ] ; then

		printMode "Creating $DESTINATION"
		mkdir -p $DESTINATION

		if [ ! -d $DESTINATION ] ; then
			printError "Unable to create $DESTINATION."
			exit 1
		fi	
		
	else
		printError "$DESTINATION does not exist (Using setup with --force parameter will create it automatically)"
		exit 1
	fi
fi

printMode "Creating $LUCENE_DIST_MAP_PATH"
mkdir -p $LUCENE_DIST_MAP_PATH/lucene-index
#--------------------------------------------------------------------------------------
#--- Check all the required parameters
ERROR_EXISTS=

if [ -z "$KEY" ] ; then
	printError "-k (key) Please provide the product installation key or please contact support@alachisoft.com"
	ERROR_EXISTS="yes";
fi

if [ "$ERROR_EXISTS" ] ; then
	exit 1;
fi

#--------------------------------------------------------------------------------------
# INSTALLMODE should be valid
case "$INSTALLMODE" in
	"0" )
		INSTALLMODE="0"
		printMode "Install Mode: $INSTALLMODE"
		;;
	"2" )
	INSTALLMODE="2"
	printMode "Install Mode: $INSTALLMODE"
	;;
	"3" )
		INSTALLMODE="3"
		printMode "Install Mode: $INSTALLMODE"
		;;
	* )
		printError "Install Mode invalid, please provide from the following: server/client"
		exit 1;
esac

#--------------------------------------------------------------------------------------
# Setting IP to be used for caches configuration files
if [ $ISCONTAINER != true ] ; then
	ip=
	if [ "$IP" ] ; then
		printMessage "Validating ip-address : $IP ..."
		ipaddress=$(hostname -I | grep -w "$IP" 2>/dev/null)
		if [ "$ipaddress" ] ; then
			printMessage "$IP is a valid ip-address"
			ip=$IP
		else
			printError "$IP is not a valid ip-address, this machine does not contain ip-address: $IP"
			exit 1;
		fi
	else
		ipaddress=$(hostname -I)
		set -- $ipaddress
		one=${1}
		if [ "$one" ] ; then		
			ip=$one
			printMessage "Selected ip-address: $ip"		
		else
			printError "Unable to find a valid ip-address."
			exit 1;
		fi
	fi
fi

#----------------------------------------------------------------------------------------------------
#--- Verify required .NET version, if unable to find the required .NET version then exit installation
VERSION=



if [ $DOTNETPATH ] && [ -d $DOTNETPATH ] ; then
    DOTNETPATH="$DOTNETPATH/dotnet"
fi

if [ -z $DOTNETPATH ] ; then
    DOTNETPATH=$(command -v dotnet)
fi

if [ $DOTNETPATH ] ; then
	versions=$($DOTNETPATH --list-runtimes | cut -f 2 -d ' ')
fi


for version in $versions
do
	v=$(echo $version | cut -c-3)
	verify $DOTNETCOREVER $v
	VERSION=$version
	if [ "$VERIFIED" = "1" ]
		then	
		if [ $INSTALLMODE = "0" ] ; then
			v=$(echo $version | cut -c-1)
			rv=$(echo $DOTNETCOREVER | cut -c-1)
			if [ "$v" = "$rv" ] ; then
				break;
			else
				VERIFIED="0"
			fi
		else
			break;
		fi
	fi		
done	

#----------------------------------------------------------------------------------------------------
# ----------------------- verify required powershell version is installed ---------------------------
PWSHHOME=$(command -v pwsh) 
VERIFIED="0"
PWSHVERSION=
#--------------------------------------------------------------------------------------
# Creating user for NCache... 
printMessage "Checking if user '$NCUSER' already exists ..."
userExists=

if [ -z $(id -u $NCUSER 2>/dev/null) ] ; then
	printMessage "Creating '$NCUSER' user ..."
	useradd -m "$NCUSER"
	passwd $NCUSER 2>/dev/null <<EOF
$PASSWORD
$PASSWORD
EOF
	printMessage "User successfully created."
	printMessage "Password of '$NCUSER' user is: $PASSWORD"
else
	printMessage "User '$NCUSER' already exists."
	printMessage ""
	userExists="yes"

	if [ "$NEWPASS" ] ; then
	passwd $NCUSER 2>/dev/null <<EOF
$PASSWORD
$PASSWORD
EOF
	fi
fi

#--------------------------------------------------------------------------------------
# All values specified, proceeding with installation
printMessage ""
printMessage "--------------------------------------------------"
printMessage "Proceeding installation with the following values:"
printMessage "--------------------------------------------------"
printMessage "Installation Key      : $KEY"
printMessage "Destination           : $DESTINATION/ncache"
printMessage ".NET Version          : $DOTNETCOREVER"
printMessage "IP Address            : $ip"
printMessage "$PRODUCT user           : $NCUSER"
printMessage "Install Mode          : $INSTALLATIONTYPE"
printMessage "--------------------------------------------------"
printMessage ""

#--------------------------------------------------------------------------------------
# Extract installation tar.gz
printMode "Extracting setup ..."
tar -zxf "$PRODUCT_TAR" -C $DESTINATION

#--------------------------------------------------------------------------------------
# Copying post installation README file
sed -i "s|<IP>|$ip|g" $DESTINATION/ncache/README

#--------------------------------------------------------------------------------------
# Verify Key...

chmod +x ${DESTINATION}/ncache/lib/license/NActivate
chmod +x ${DESTINATION}/ncache/lib/Alachisoft.NCache.License.NetCore.dll
chmod +x ${DESTINATION}/ncache/libexec/Alachisoft.NCache.License.NetCore.dll
chmod +x ${DESTINATION}/ncache/lib/Alachisoft.NCache.License.NetCore
chmod +x ${DESTINATION}/ncache/lib/NActivate

${DESTINATION}/ncache/lib/Alachisoft.NCache.License.NetCore $KEY "" > /dev/null
res=$?


if [ $res = 0 ] ;	then
	printError "Invalid installation key. Recheck key or please contact support@alachisoft.com\n"
	rm -r $DESTINATION/ncache 
	exit 1
elif [ $res = 3 ] ; then
	printError "NCache cannot be installed on Azure virtual Machine. Please use NCache Community Software (https://azuremarketplace.microsoft.com/en-us/marketplace/apps/ncache.comm-linux) available on Azure Marketplace. Please contact sales@alachisoft.com if you have any questions.\n"
	rm -r $DESTINATION/ncache 
	exit 1
elif [ $res = 4 ] ; then
	printError "NCache cannot be installed on AWS virtual Machine. Please use NCache Community Software (https://aws.amazon.com/marketplace/pp/prodview-zd6dbx5652p4m) available on AWS Marketplace. Please contact sales@alachisoft.com if you have any questions.\n"
	rm -r $DESTINATION/ncache 
	exit 1
elif [ $res = 5 ] ; then
	INSTALLTYPE="az"
	ENV="azure"
elif [ $res = 6 ] ; then
	INSTALLTYPE="aw"
	ENV="aws"

fi

#--------------------------------------------------------------------------------------
# The registration email is the one embedded in the installation key.
EMAIL=$(${DESTINATION}/ncache/lib/Alachisoft.NCache.License.NetCore --email "$KEY" 2>/dev/null)
printMessage "Registered Email      : $EMAIL"




#--------------------------------------------------------------------------------------
printMode "Switching to directory $DESTINATION/ncache/bin/service ..."
cd $DESTINATION/ncache/bin/service

if [ $ISCONTAINER != true ] ; then
	printMode "Setting ip-address in Alachisoft.NCache.Daemon.dll.config ..."
	sed -i "s/<IP>/$ip/g" "Alachisoft.NCache.Daemon.dll.config"
fi

if [ $INSTALLMODE = "0" ] ; then
	sed -i "s/<FeatureUsageLogging>/true/g" "Alachisoft.NCache.Daemon.dll.config"
	sed -i "s/<FeatureUsageStats>/true/g" "Alachisoft.NCache.Daemon.dll.config"
else
	sed -i "s/<FeatureUsageLogging>/false/g" "Alachisoft.NCache.Daemon.dll.config"
	sed -i "s/<FeatureUsageStats>/false/g" "Alachisoft.NCache.Daemon.dll.config"
fi

printMode "Switching to directory $DESTINATION/ncache/config ..."
cd $DESTINATION/ncache/config

if [ $ISCONTAINER != true ] ; then
	printMode "Setting ip-address to $ip ..."

	printMode "Setting ip-address in client.ncconf ..." 
	sed -i "s/<IP>/$ip/g" "client.ncconf"

	printMode "Setting ip-address in config.ncconf ..." 
	sed -i "s/<IP>/$ip/g" "config.ncconf"
fi

printMode "Setting install-dir in ncinfo.xml ..."
loc="$DESTINATION/ncache/"

sed -i "s|<INSTALLDIR>|$loc|g" "ncinfo.xml"

printMode "Setting install-type in ncinfo.xml ..."
sed -i "s/<INSTALLTYPE>/$INSTALLTYPE/g" "ncinfo.xml"

printMode "Setting email in ncinfo.xml ..."
sed -i "s/<EMAIL>/$EMAIL/g" "ncinfo.xml"

printMode "Setting first-name in ncinfo.xml ..."
sed -i "s/<FIRSTNAME>/$FIRST_NAME/g" "ncinfo.xml"

printMode "Setting last-name in ncinfo.xml ..."
sed -i "s/<LASTNAME>/$LAST_NAME/g" "ncinfo.xml"

printMode "Setting company name in ncinfo.xml ..."
sed -i "s/<COMPANY>/$COMPANY_NAME/g" "ncinfo.xml"

INSTALLCODE=

case $INSTALLMODE in
	"0")
		# OSS server install code (NC-OSS-53, same as the Windows MSI). The old NC-PROFO-53 code made the
		# server resolve its edition as None, which leaves the cluster version stamp null and breaks clustering.
		INSTALLCODE="p2exh7amceDwAaB0pyIjY+cHhkc=" 
		;;
	"3" ) 
		INSTALLCODE="p2exdrd35kcRgNAhR5OHAkMDxydmpw=="                     	             
		;;
	"2")
		INSTALLCODE="p2exdsfHxmGQ4DGwg7cSMxP3N5a3"
		;;
esac

printMode "Setting install-code in ncinfo.xml ..."
sed -i "s/<INSTALLCODE>/$INSTALLCODE/g" "ncinfo.xml"

if [ ! -f /usr/lib/.ncinfo.xml ]; then
	cp $DESTINATION/ncache/config/ncinfo.xml /usr/lib
fi
rm $DESTINATION/ncache/config/ncinfo.xml

if [ ! -f /usr/lib/nclicense.xml ]; then
    cp $DESTINATION/ncache/config/nclicense.xml /usr/lib
fi
rm $DESTINATION/ncache/config/nclicense.xml

printMode "Changing directory to $DESTINATION/ncache"
loc="$DESTINATION/ncache"
cd $DESTINATION/ncache/

#--------------------------------------------------------------------------------------
# Prepare PowerShell Tools... 

cd $DESTINATION/ncache/lib/tools/ncacheps
sed -i "s|<NCHOME>|$loc|g" ncacheps.psd1
PWSHHOME=$DESTINATION/ncache/lib/tools/powershell
chmod +x $PWSHHOME/pwsh
if [ $PWSHHOME ]
then	
	# pwshhome=$(readlink -f $PWSHHOME | sed -e "s/pwsh/Modules/g")
	# pwshhome="${pwshhome}/"
	ln -s /$DESTINATION/ncache/lib/tools/ncacheps $PWSHHOME/Modules/ncacheps
	chmod +x $DESTINATION/ncache/lib/tools/ncacheps/*
fi

#--------------------------------------------------------------------------------------
# Prepare Modules

# cd $DESTINATION/ncache/bin/modules/lucene-net-4.8

# cp $DESTINATION/ncache/bin/modules/lucene-net-4.8/*.dll $DESTINATION/ncache/lib

# rm $DESTINATION/ncache/lib/*.CachingModule.dll

#--------------------------------------------------------------------------------------
#--- Change ownership of ncache related files and folder
printMode "Making $NCUSER the owner of $DESTINATION/ncache ..."
chown -R $NCUSER:$NCUSER $LUCENE_DIST_MAP_PATH
chown -R $NCUSER:$NCUSER $DESTINATION/ncache
chmod -R +664 $DESTINATION/ncache/config
chmod -R +664 $DESTINATION/ncache/log-files
chmod -R g+s $DESTINATION/ncache/log-files
chown  	$NCUSER:$NCUSER /usr/lib/ncinfo.xml
chown  	$NCUSER:$NCUSER /usr/lib/nclicense.xml

#--------------------------------------------------------------------------------------
# Installing Service...
if [ $ISCONTAINER != true ] ; then
	# Installing NCache Service...
	printMode "Changing directory to $DESTINATION/ncache/bin/service"
	cd $DESTINATION/ncache/bin/service
	printMode "Installing service"

	printMode "Setting DOTNETHOME in ncached.service ..."
	sed -i "s|<DOTNETHOME>|$DOTNETPATH|g" "ncached.service"

	printMode "Setting INSTALLDIR in ncached.service ..."
	sed -i "s|<INSTALLDIR>|$loc|g" "ncached.service"

	cp $DESTINATION/ncache/bin/service/ncached.service /etc/systemd/system
	rm $DESTINATION/ncache/bin/service/ncached
	rm $DESTINATION/ncache/bin/service/ncached.service

	printMode "Daemon Coppied Successfully."
	
else

	cd $DESTINATION/ncache/bin/service/
	printMode "Installing service"

	printMode "Setting DOTNETHOME in ncached ..."
	sed -i "s|<DOTNETHOME>|$DOTNETPATH|g" "ncached"

	printMode "Setting INSTALLDIR in ncached ..."
	sed -i "s|<INSTALLDIR>|$loc|g" "ncached"

	cp $DESTINATION/ncache/bin/service/ncached /etc/init.d/
	chmod +x /etc/init.d/ncached
	rm $DESTINATION/ncache/bin/service/ncached
	rm $DESTINATION/ncache/bin/service/ncached.service
	printMode "Daemon Coppied Successfully."
fi

#--------------------------------------------------------------------------------------


printMessage "Installation completed successfully."

if [ $KEYVALID = "true" ] ; then 
		printMessage ""
		printMessage "NCache has been installed successfully, but your Install Key has expired. Before using NCache, you must activate it with a valid Install Key or a purchased NCache license key."
		printMessage ""
		printMessage "NOTE: Please contact sales (sales@alachisoft.com) to obtain extension for the Install Key or purchase NCache and obtain a license key."
		printMessage ""
fi

#--------------------------------------------------------------------------------------
#--- Starting ncache service ...

if [ $ISCONTAINER != true ] ; then
	printMessage "Starting NCache service ..."
	systemctl daemon-reload
	systemctl enable ncached.service
	systemctl start ncached.service		

	

sleep 3 &
wait
	if [ $ENABLE_DUMP = "true" ] ; then
		echo 0 | tee /proc/sys/kernel/yama/ptrace_scope > /dev/null
	fi
	
	CURLPATH=$(command -v curl)
	if [ -n "$CURLPATH" ]
	then	
		PostInstallationActivity
	fi
	
	printMessage "NCacheServer.BindToIP             = $ip  " 
	printMessage "NCacheServer.Port                 = 9800 " 
	printMessage "NCacheServer.ManagementPort       = 9803 " 
	printMessage "Cache host ports                  = 9831-9880 " 
	printMessage "Cache cluster ports               = 9881-9980 " 
	NCPID=$(pgrep -f  Alachisoft.NCache.Daemon)
	if [ $NCPID ] ; then
		printMessage "NCache service started successfully with following process-id (pid): $NCPID" 
	else
		printMessage "Job for ncached.service failed because the control process exited with error code.\nSee \"systemctl status ncached.service\" and \"journalctl -xe\" for details."
	fi
	
fi



printMessage "To call Linux based commands, just make sure that your PATH includes ${DESTINATION}/ncache/bin/tools and then find out about all the commands like this:"
printMessage ""
printMessage "	$ ls ${DESTINATION}/ncache/bin/tools"

printMessage ""
printMessage "Read more details below:"
printMessage ""
printMessage "	https://www.alachisoft.com/resources/docs/ncache/getting-started/ncache-oss.html"
printMessage "	https://www.alachisoft.com/resources/docs/ncache/admin-guide/"
printMessage "	https://www.alachisoft.com/resources/docs/ncache/prog-guide/"
printMessage " 	https://github.com/Alachisoft/NCache/tree/master/Samples"
