##########################
# Initialisation
##########################

# To live try:
# source <( curl https://raw.githubusercontent.com/mrjk/linux-personal-env/master/bash/bash.bashrc)
# To install locally
# curl https://raw.githubusercontent.com/mrjk/linux-personal-env/master/bash/bash.bashrc > ~/.bashrc

# If not running interactively, don't do anything
case $- in
	*i*)
	;;
	*) 
		return
	;;
esac


##########################
# Func: Global variables
##########################

shell_global_variable () {
	HOSTNAME=$(head -n 1 /etc/hostname)

	# Custom variables
	##########################

	# Regex to match IP
	RGX_IP='(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)'
	RGX_IP='([0-2][0-9]{2}\.){3}'

	# Regex to match emplty lines and comments ... use with grep -E -v
	RGX_EL='^[[:blank:]]*#|^$'

	# Match a username
	RGX_USER='[a-z0-9-]'

	# Match a domain ANSI
	RGX_DOM='([a-z][a-z0-9\-]+(\.|\-*\.))+[a-z]{2,6}'
	RGX_DOM='[a-z0-9-]+(\.[a-z0-9-]+)?\.[a-z0-9-]{2,6}'

	# Match Hexadecimal, 
	RGX_HEX='#?([a-f0-9]{6}|[a-f0-9]{3})'

	# Match email
	RGX_EMAIL='([a-z0-9_\.-]+)@([\da-z\.-]+)\.([a-z\.]{2,6})'

	# Match URL
	RGX_URL='(https?:\/\/)?([\da-z\.-]+)\.([a-z\.]{2,6})([\/\w \.-]*)*\/?'
}


##########################
# Func: Global color
##########################

shell_global_color () {
	# Easy
	RED='\[\033[31m\]'
	GREEN='\[\033[32m\]'
	YELLOW='\[\033[33m\]'
	BLUE='\[\033[34m\]'
	PURPLE='\[\033[35m\]'
	CYAN='\[\033[36m\]'
	WHITE='\[\033[37m\]'
	NIL='\[\033[00m\]'

	# Reset
	Color_Off='\e[0m'       # Text Reset

	# Regular Colors
	Black='\e[0;30m'        # Black
	Red='\e[0;31m'          # Red
	Green='\e[0;32m'        # Green
	Yellow='\e[0;33m'       # Yellow
	Blue='\e[0;34m'         # Blue
	Purple='\e[0;35m'       # Purple
	Cyan='\e[0;36m'         # Cyan
	White='\e[0;37m'        # White

	# Bold
	BBlack='\e[1;30m'       # Black
	BRed='\e[1;31m'         # Red
	BGreen='\e[1;32m'       # Green
	BYellow='\e[1;33m'      # Yellow
	BBlue='\e[1;34m'        # Blue
	BPurple='\e[1;35m'      # Purple
	BCyan='\e[1;36m'        # Cyan
	BWhite='\e[1;37m'       # White

	# Underline
	UBlack='\e[4;30m'       # Black
	URed='\e[4;31m'         # Red
	UGreen='\e[4;32m'       # Green
	UYellow='\e[4;33m'      # Yellow
	UBlue='\e[4;34m'        # Blue
	UPurple='\e[4;35m'      # Purple
	UCyan='\e[4;36m'        # Cyan
	UWhite='\e[4;37m'       # White

	# Background
	On_Black='\e[40m'       # Black
	On_Red='\e[41m'         # Red
	On_Green='\e[42m'       # Green
	On_Yellow='\e[43m'      # Yellow
	On_Blue='\e[44m'        # Blue
	On_Purple='\e[45m'      # Purple
	On_Cyan='\e[46m'        # Cyan
	On_White='\e[47m'       # White

	# High Intensity
	IBlack='\e[0;90m'       # Black
	IRed='\e[0;91m'         # Red
	IGreen='\e[0;92m'       # Green
	IYellow='\e[0;93m'      # Yellow
	IBlue='\e[0;94m'        # Blue
	IPurple='\e[0;95m'      # Purple
	ICyan='\e[0;96m'        # Cyan
	IWhite='\e[0;97m'       # White

	# Bold High Intensity
	BIBlack='\e[1;90m'      # Black
	BIRed='\e[1;91m'        # Red
	BIGreen='\e[1;92m'      # Green
	BIYellow='\e[1;93m'     # Yellow
	BIBlue='\e[1;94m'       # Blue
	BIPurple='\e[1;95m'     # Purple
	BICyan='\e[1;96m'       # Cyan
	BIWhite='\e[1;97m'      # White

	# High Intensity backgrounds
	On_IBlack='\e[0;100m'   # Black
	On_IRed='\e[0;101m'     # Red
	On_IGreen='\e[0;102m'   # Green
	On_IYellow='\e[0;103m'  # Yellow
	On_IBlue='\e[0;104m'    # Blue
	On_IPurple='\e[0;105m'  # Purple
	On_ICyan='\e[0;106m'    # Cyan
	On_IWhite='\e[0;107m'   # White
}


##########################
# Func: shell PS1
##########################

# Full function wrapper
shell_ps1 () {
	shell_ps1_advanced
	#shell_ps1_simple
}

# PS1 shell reset (in case of emergency)
shell_ps1_simple () {
	PS1='\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
	#PS1='$USER@$(hostname):$PWD\$ '
}

# Full function
shell_ps1_advanced () {

	# Define dynamic prompt variables (Fucking bashisms :-()
	local PS1_RETURN="\$(
		PS1_EXIT=\$?; 
		[[ \$PS1_EXIT == 0 ]] ||  echo -n \"\[$Red\]\${PS1_EXIT}\[${Color_Off}\] \"
	)"
	
	local PS1_PATH="\$(
		if [ -s \"\${PWD}\" ] ; then
		#	PS1_DF=\$(command df -P \"\${PWD}\" | grep -E -o '[0-9]{1,3}%' | grep -E -o '[0-9]{1,3}');
			PS1_DF=\$(command timeout 1s df -P \"\${PWD}\" | awk 'END {print \$5} {sub(/%/,\"\")}');

			if [ \"\${PS1_DF:-0}\" -gt 95 ]; then
				PS1_PATH=\"\[$Red\]:\"
			elif [ \"\${PS1_DF:-0}\" -gt 90 ]; then
				PS1_PATH=\"\[$Yellow\]:\"
			else
				PS1_PATH=\"\[$White\]:\"
			fi
		else
			# Current directory is size '0' (like /proc, /sys etc).
			PS1_PATH=\"\[$Yellow\]:\";
		fi
		if [ -w \"\${PWD}\" ] ; then
			PS1_PATH=\"\${PS1_PATH}\[$Blue\]\w\"
		else
			# No 'write' privilege in the current directory.
			PS1_PATH=\"\${PS1_PATH}\[$Yellow\]\w\"
		fi

		echo -e \"\${PS1_PATH}\"
	)"

	# Get jobs
	local PS1_JOBS="\$(
		PS1_JOBS='';
		PS1_JOBS_RUNNING=\$(jobs -r | wc -l);
		PS1_JOBS_STOPPED=\$(jobs -s | wc -l);
		if [ \${PS1_JOBS_RUNNING} -gt 0 ] || [ \${PS1_JOBS_STOPPED} -gt 0 ]
		then
			if [ \${PS1_JOBS_RUNNING:-0} -gt 0 ]; then
				PS1_JOBS_RUNNING=\"\[$Green\]\${PS1_JOBS_RUNNING}\[$Color_Off\]\"
			else
				PS1_JOBS_RUNNING=''
			fi

			if [ \${PS1_JOBS_STOPPED:-0} -gt 0 ]; then
				PS1_JOBS_STOPPED=\"\[$Yellow\]\${PS1_JOBS_STOPPED}\[$Color_Off\]\"
			else
				PS1_JOBS_STOPPED=''
			fi
			PS1_JOBS=\"\${PS1_JOBS_RUNNING}:\${PS1_JOBS_STOPPED} \";
		else
			PS1_JOBS=''
		fi
		echo -e \"\${PS1_JOBS}\";
	)"

	# Time execution checker

	# Maximal time to consider prompt as slow in ms
	local PS1_MAX_EXEC_TIME=500
	# Number of time needed before swithing to basic prompt
	local PS1_MAX_TIME=3
	# Time windows to check
	local PS1_MAX_EXEC_DELAY=60
	# Time before reloading full PS1 after showing simple prompt
	local PS1_DELAY_RELOAD=300

	# Debug
#	local PS1_MAX_EXEC_TIME=5
#	local PS1_MAX_TIME=3
#	local PS1_MAX_EXEC_DELAY=60
#	local PS1_DELAY_RELOAD=30
	
	local PS1_TMP_FILE=/tmp/.load-$(whoami)
	chown $(whoami):$(whoami) ${PS1_TMP_FILE} 2>/dev/null
	local PS1_START="\$(
		if [ -f ${PS1_TMP_FILE} ] && [ \"\$(cat ${PS1_TMP_FILE} | grep -E -o '^reset')\" = \"reset\" ]
		then
			echo '\u@\h:\[\033[01;34m\]\w\[\033[00m\]\\$ '
			if [ \$((\$(date +%s) - \$(stat -c %Y ${PS1_TMP_FILE}) )) -gt ${PS1_DELAY_RELOAD} ]
			then
				echo -n \"Shell: full prompt reactivated.\n\"
				> ${PS1_TMP_FILE};
			fi
		else
			ts=\$(date +%s%N); 
			echo -e \""
	local PS1_STOP="\"; 
			tt=\$(((\$(date +%s%N) - \${ts})/1000000));
			if [ \${tt} -gt ${PS1_MAX_EXEC_TIME} ]
			then
				echo 1 >> ${PS1_TMP_FILE};
					if [ \$((\$(date +%s) - \$(stat -c %Y ${PS1_TMP_FILE}) )) -gt ${PS1_MAX_EXEC_DELAY} ] || [ \$(wc -l ${PS1_TMP_FILE} | grep -E -o '^[0-9]{1,3}') -gt ${PS1_MAX_TIME} ]
					then
						echo "reset" > ${PS1_TMP_FILE};
						echo -n \"Shell: prompt is taking more than ${PS1_MAX_EXEC_TIME}ms to anwser. Normal prompt will be reactivated in ${PS1_DELAY_RELOAD}s. Execute 'rm ${PS1_TMP_FILE}' to force.\n\" ;
					fi
			fi 
		fi
	)"

	# Define static prompt variables
	local PS1_ACOUNT="\[$White\]\\$ "
	local PS1_CHROOT_DEB="${debian_chroot:+($debian_chroot)}"

	# Set variable identifying the chroot you work in (used in the prompt below)
	if [ -z "${debian_chroot:-}" ] && [ -r /etc/debian_chroot ]; then
	    local debian_chroot=$(cat /etc/debian_chroot)
	fi

	# Define prompt depending user
	if [ $(id -u) -eq 0 ];
	then # you are root, make the prompt red
		# Are you root ?
		local PS1_USER="\[$Green\]\u"
		# In green
	elif [ -n "$(cat /etc/passwd  | grep $(whoami)  | grep -E -v ':/bin/(ba|z|t)?sh')" ]; then
		# The you are a no login user ...
		local PS1_USER="\[$Red\]\u"
		# In red
	elif [ $(id -u) -lt 1000 ]; then
		# Are you a system user ?
		local PS1_USER="\[$Yellow\]\u"
		# In orange
	elif [ $(id -u) -ge 1000 ]; then
		# Are you a regular user ?
		local PS1_USER="\[$White\]\u"
		# In white
	fi

	# Detect serial connection (virtualisation, ttySx)
	if [ $(ps ax | grep $$ | awk '{ print $2 }' | grep 'ttyS.' | wc -l ) -gt 0 ]; then
		local PS1_HOST="@\[$Red\]\h"
	else
		local PS1_HOST="\[$Green\]@\h"
	fi

	# Set the prompt depending the shell
	if [ "${CURRENT_SHELL}" = "bash" ]; then
		PS1="\[$Color_Off\]${PS1_RETURN}${PS1_START}${PS1_JOBS}${PS1_USER}${PS1_HOST}${PS1_PATH}${PS1_ACOUNT}\[$Color_Off\]${PS1_STOP}"
	elif [ "${CURRENT_SHELL}" = "dash" ] ; then
		PS1='$USER@$HOSTNAME:$PWD\$ '
	else
		PS1='${debian_chroot:+($debian_chroot)}\[\033[01;32m\]\u@\h\[\033[00m\]:\[\033[01;34m\]\w\[\033[00m\]\$ '
	fi
}


##########################
# Func: Bash alias
##########################

bash_alias () {
	alias ll='ls -lh'
	alias la='ls -lAh'
	alias l='ls -ClFh'
	alias ltr='ls -ahltr'
	alias lsd="ls -l | grep ^d"

	alias mkdir='mkdir -p'

	alias ..='cd ..'
	alias ...='cd ../..'
	alias ....='cd ../..'

	alias h='history'
	alias j='jobs -l'

	alias vih='vim /etc/hosts '
	alias vit='vim /etc/fstab '
	alias vif='vim /etc/network/interfaces '
	alias diff='colordiff '
	alias tmount='mount |column -t '

	alias wgets='wget --no-check-certificate '
	alias wgeth='wget --no-check-certificate -S -O /dev/null '
	alias uncmt="grep '^[^#|^$|^ *$]' "
	alias monip='wget -q -O - "$@" monip.org | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}"'
	alias monhost='echo "My host is ..."; host $(wget -q -O - "$@" monip.org | grep -o "[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}\.[0-9]\{1,3\}")'
	alias text2ascii='tail --bytes=+4'

	alias iptlist='sudo /sbin/iptables -L -n -v --line-numbers'
	alias iptlistin='sudo /sbin/iptables -L INPUT -n -v --line-numbers'
	alias iptlistout='sudo /sbin/iptables -L OUTPUT -n -v --line-numbers'
	alias iptlistfw='sudo /sbin/iptables -L FORWARD -n -v --line-numbers'

	# Typo correction
	alias cd..='cd ..'

	# List directory when moving
	#cd() { builtin cd "$@"; ll; }

	# Chroot helper
	chroot_mount_system () {
		if [ -d $1 ]; then
			mount -t proc none $1/proc
			mount -obind /dev $1/dev
			mount -obind /sys $1/sys
			echo "Then: chroot $1 /bin/bash "
		else
			echo "Usage: chroot_mount_system <dir>"
		fi
	}

	# SSH Helper
	alias ssh_unsecure='ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no CheckHostIP=no'
	alias ssh_local='ssh -o CheckHostIP=no '
}


##########################
# Func: Command not found
##########################

bash_completion () {

	# SSH Host completion	
	if [ -e ~/.ssh/known_hosts ] ; then
		complete -W "$(echo `cat ~/.ssh/known_hosts | cut -f 1 -d ' ' | sed -e s/,.*//g | uniq | grep -v "\["`;)" ssh
		# Note: HashKnownHosts need to be set 'no' in /etc/ssh/ssh_config
	fi

}


##########################
# Func: Command not found
##########################

shell_command_not_found () {
	# if the command-not-found package is installed, use it
	if [ -x /usr/lib/command-not-found -o -x /usr/share/command-not-found/command-not-found ]; then
		command_not_found_handle () {
			# check because c-n-f could've been removed in the meantime
			if [ -x /usr/lib/command-not-found ]; then
				/usr/bin/python /usr/lib/command-not-found -- "$1"
				return $?
			elif [ -x /usr/share/command-not-found/command-not-found ]; then
				/usr/bin/python /usr/share/command-not-found/command-not-found -- "$1"
				return $?
			else
				printf "%s: command not found\n" "$1" >&2
				return 127
			fi
		}
	fi
}

##########################
# Func: Bash command color
##########################

bash_command_color () {

	if [ -x /usr/bin/dircolors ]; then
		test -r ~/.dircolors && eval "$(dircolors -b ~/.dircolors)" || eval "$(dircolors -b)"
		alias ls='ls --color=auto'
		alias dir='dir --color=auto'
		alias vdir='vdir --color=auto'
		
		alias grep='grep --color=auto'
		alias fgrep='fgrep --color=auto'
		alias egrep='egrep --color=auto'
	fi


	if [ -x /usr/bin/colordiff ]; then
		alias diff='colordiff' 
	fi


	# Pager config and colors
	#export MANPAGER='/usr/bin/most -S'
	export MANPAGER='/usr/bin/less'

	LESS_TERMCAP_mb=$'\E[01;31m'
	LESS_TERMCAP_us=$'\E[01;32m'
	LESS_TERMCAP_md=$'\E[01;31m'
	LESS_TERMCAP_se=$'\E[0m'
	LESS_TERMCAP_so=$'\E[01;44;33m'
	LESS_TERMCAP_ue=$'\E[0m'
	LESS_TERMCAP_me=$'\E[0m'


	# Ajout log en couleurs
	ctail() { tail -f $1 | ccze -A; }
	cless() { ccze -A < "$1" | less -R; }
}



##########################
# Func: Bash config
##########################


bash_config () {
	##########################
	# History management
	##########################

	# Force timestamp in history
	export HISTTIMEFORMAT='%F %T '

	# Ignore duplicates and lines starting by a space
	export HISTCONTROL=""

	# for setting history length see HISTSIZE and HISTFILESIZE in bash(1)
	export HISTSIZE=10000
	export HISTFILESIZE=2000

	if [ -w ~/.bash_history ]; then
#		echo "Bash: enabling history file"
		export HISTFILE=~/.bash_history
	else
#		echo "Bash: disabling history file"
		unset HISTFILE
	fi


	##########################
	# Misc
	##########################

	# Disable mail check
	unset MAILCHECK

	# Update shell output according to the terminal size
	shopt -s checkwinsize

	# Load other aliases
	if [ -f ~/.bash_aliases ]; then
	    . ~/.bash_aliases
	fi

	# Synchronise history
	shopt -s histappend
	export PROMPT_COMMAND="history -a"

	# Enable completion
	if ! shopt -oq posix; then
	  if [ -f /usr/share/bash-completion/bash_completion ]; then
	    . /usr/share/bash-completion/bash_completion
	  elif [ -f /etc/bash_completion ]; then
	    . /etc/bash_completion
	  fi
	fi

	# Bash correction
	shopt -s autocd
	shopt -s cdspell
	shopt -s checkjobs
	shopt -s hostcomplete
	shopt -s nocaseglob
}



##########################
# Function calls
##########################

# Checking the shell
case $(readlink -f $SHELL) in
	*/zsh) 
		CURRENT_SHELL="zsh"
		;;
	*/bash)
		CURRENT_SHELL="bash";
		;;
	*/dash)
		CURRENT_SHELL="dash";
		;;
	*)
		# assume something else
		CURRENT_SHELL="none"
esac

# Preset
shell_global_variable
shell_global_color
shell_ps1
shell_command_not_found

bash_alias
bash_command_color

if [ ${CURRENT_SHELL} = "bash" ]; then
	bash_config
	bash_completion
fi
