#!/bin/bash
#
#Copyright 2012 - 2018 Hexagon, CurlyMo, mk01 & mkreisl <development@xbian.org>
#
#This file is part of XBian - XBMC on the Raspberry Pi.
#
#XBian is free software: you can redistribute it and/or modify it under the
#terms of the GNU General Public License as published by the Free Software
#Foundation, either version 3 of the License, or (at your option) any later
#version.
#
#XBian is distributed in the hope that it will be useful, but WITHOUT ANY
#WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
#FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
#details.
#
#You should have received a copy of the GNU General Public License along
#with XBian. If not, see <http://www.gnu.org/licenses/>

#|------------------------------------|
#|          Global variables          |
#|------------------------------------|

IFACES_CONFIG=/etc/network/interfaces

# The arguments this module accepts
ARGUMENTS=(list status dhcp static credentials scan restart progress type);

#|------------------------------------|
#|          Include files             |
#|------------------------------------|

source $BASEPATH/modules/network/functions
if [ $GUIMODE -eq 1 ]; then
	source $BASEPATH/modules/network/dialogs
fi
source $BASEPATH/functions/markup
[ "$DEBUG" = yes ] && . $BASEPATH/functions/dtrap

#|------------------------------------|
#|           Main program             |
#|------------------------------------|

# Executes the GUI version of this module
function showGUIFn() {
	showInterfacesSelectGUIFn;
	if [ $? -eq 0 ]; then
		return 0
	fi
}

function showInterfacesSelectGUIFn() {
	# Notify user that interfaces are loading
	showInterfacesLoadingDlg
	# Fetch all available interfaces and prepare menu
	IFACES=($(listNetworkInterfacesFn))
	if [ ! -z "$IFACES" ]; then
		showInterfacesSelectDlg "$IFACES"
		if [ $? -eq 0 ]; then
			# Save selected interface to a variable
			IFACE=${IFACES[$(($RETURN-1))]}
			# Get current configuration
			IFACE_DATA=$(readNetworkConfigurationFn "$IFACE")
			# Get mode
			MODE=$(echo -e "$IFACE_DATA" | grep 'mode ' | cut -f 2 -d" ")
			
			showIPModeConfigGUIFn;
		fi
	else
		showNoInterfacesAvailableDlg
	fi
}

function showIPModeConfigGUIFn() {
	# Show DHCP/Static selection
	showIPModeConfigDlg "$MODE"
	if [ $? -eq 0 ]; then
		# Set Static/DHCP Settings
		if [ $RETURN -eq 1 ]; then
			# DHCP Selected
			setInterfaceDhcpFn "$IFACE"
			STATUS=$?;
			#showInterfaceDhcpSuccessDlg
			MODE="dhcp"

		elif [ $RETURN -eq 2 ]; then
			# Static IP Selected
			showInterfaceStaticGUIFn "$IFACE" "$IFACE_DATA"
			STATUS=$?;
			MODE="static"
		else
			showInterfaceStaticGUIFn "$IFACE" "$IFACE_DATA" disable
			STATUS=3
		fi

		if [ $STATUS -eq 1 ]; then
			# If needed, ask for wireless credentials
			ISWLAN=$(echo -e "$IFACE" | grep -E 'wlan|ra')
			if [ ! -z "$ISWLAN" ]; then
				showWlanScanGUIFn "$IFACE" "$IFACE_DATA"
			else
				# Configuration done
				showRestartGUIFn "$IFACE" "LAN"
				showGUIFn
			fi
		fi
	else
		# Configuration done
		showGUIFn
	fi
}

function showInterfaceStaticGUIFn() {
	IP=$(echo "$2" | grep ip | cut -f 2 -d" ")
	NETMASK=$(echo "$2" | grep netmask | cut -f 2 -d" ")
	GATEWAY=$(echo "$2" | grep gateway | cut -f 2 -d" ")
	NAMESERVER1=$(echo "$2" | grep nameserver1 | cut -f 2 -d" ")
	NAMESERVER2=$(echo "$2" | grep nameserver2 | cut -f 2 -d" ")

	if [ "$3" = "disable" ]; then
		IFS=$'\n';
		setInterfaceStaticFn "$1" "$IP" "$NETMASK" "$GATEWAY" "$NAMESERVER1" "$NAMESERVER2" $3
		IFS=$ORIGINALIFS;
		showInterfaceDisableSuccessDlg
		showGUIFn
	else
		showInterfaceStaticDlg "$IP" "$NETMASK" "$GATEWAY" "$NAMESERVER1" "$NAMESERVER2"
		if [ $? -eq 0 ]; then
			IFS=$'\n';
			STATICCONF=($(echo -e "$RETURN"))
			IFS=$ORIGINALIFS;
			if [ ${#STATICCONF[@]} -gt 1 ]; then
				IP="${STATICCONF[0]}"
				NETMASK="${STATICCONF[1]}"
				GATEWAY="${STATICCONF[2]}"
				NAMESERVER1=""
				NAMESERVER2=""
				if [ ${#STATICCONF[@]} -gt 3 ]; then
					NAMESERVER1="${STATICCONF[3]}"
				fi
				if [ ${#STATICCONF[@]} -gt 4 ]; then
					NAMESERVER2="${STATICCONF[4]}"
				fi
				# Validation of arguments is done inside this function
				RESULT=$(setInterfaceStaticFn "$1" "$IP" "$NETMASK" "$GATEWAY" "$NAMESERVER1" "$NAMESERVER2"; echo $?)
				if [ $RESULT -eq 1 ]; then
					showInterfaceStaticSuccessDlg
					if [[ $1 =~ "wlan" ]] || [[ $1 =~ "ra" ]]; then
						showWlanScanGUIFn "$1" "$2"
					else
						showRestartGUIFn $1 "LAN"
						showGUIFn;
					fi
				else
					showInterfaceStaticErrorDlg
					showInterfaceStaticGUIFn "$1" "$2"
				fi
			else
				showInterfaceStaticErrorDlg
				showInterfaceStaticGUIFn "$1" "$2"
			fi
		else
			showIPModeConfigGUIFn
		fi
	fi
}

function showWlanScanGUIFn() {

	SSID=$(echo -e "$2" | sed -ne 's/ssid[\ ]\(.*\)/\1/p')
	WLANKEY=$(echo -e "$2" | sed -ne 's/key[\ ]\(.*\)/\1/p')
	PROTECTION=$(echo "$2" | grep protection | cut -f 2 -d" ")

	showScanForWLANDlg;
	
	if [ $? -eq 0 ]; then
		if [ $RETURN -eq 2 ]; then
			CUSTOM=1;
		else
			CUSTOM=0;
		fi
		if [ $CUSTOM -eq 1 ]; then	
			showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
		else
			showScanningForNetworksDlg;
			scanWLANNetworksFn $1
			showAvailableWLANDlg "$SSID" "${WNETWORKS[@]}"
			if [ $? -eq 0 ]; then
				if [ ! -z $RETURN ]; then
					IFS=",";
					WNETWORK=(${WNETWORKS[$(($RETURN-1))]});
					if [ "${WNETWORK[2]}" == "off" ] || [ "${WNETWORK[1]}" == "Open" ]; then
						PROTECTION="Open";
					elif [ "${WNETWORK[1]}" == "WPA" ] || [ "${WNETWORK[1]}" == "WPA2" ]; then
						PROTECTION="WPA"
					else
						PROTECTION="WEP";
					fi

					if [ "$SSID" != "$(echo "${WNETWORK[0]}" | awk '{print substr($0,2,length-2)}')" ]; then
						SSID=$(echo "${WNETWORK[0]}" | awk '{print substr($0,2,length-2)}');
						fetchWLANCredentialsFn "$PROTECTION" "$SSID"
					fi
					showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
				else
					showWlanScanGUIFn $1 $2
				fi
			else
				showWlanScanGUIFn $1 $2
			fi
		fi
	else
		showIPModeConfigGUIFn;
	fi
}

function showWlanProtectionGUIFn() {
	CUSTOM=$4
	PROTECTION=$3
	if [ $CUSTOM -eq 1 ]; then
		showWlanModeConfigDlg "$PROTECTION"
		if [ $? -eq 0 ]; then
			NEWPROTECTION="$RETURN"
		else
			showWlanScanGUIFn $1 $2
			return 0;	
		fi			
	else
		if [ $PROTECTION == "Open" ]; then
			NEWPROTECTION=3;
		elif [ $PROTECTION == "WPA" ]; then
			NEWPROTECTION=1
		else
			NEWPROTECTION=2;
		fi	
	fi
	
	if [ $NEWPROTECTION -lt 3 ]; then
		showInterfaceCredentialsDlg "$SSID" "$WLANKEY"
		if [ $? -eq 0 ]; then
			IFS=$'\n';
			CREDENTIALS=($(echo "$RETURN"))
			IFS=$ORIGINALIFS;
			if [ ${#CREDENTIALS[@]} -eq 2 ];then
				SSID="${CREDENTIALS[0]}"
				WLANKEY="${CREDENTIALS[1]}"
				if [ $NEWPROTECTION -eq 1 ]; then
					setInterfaceWlanCredentials "$1" "WPA" "$SSID" "$WLANKEY"
				else
					setInterfaceWlanCredentials "$1" "WEP" "$SSID" "$WLANKEY"
				fi
				
				showInterfaceCredentialsSuccessDlg
				showRestartGUIFn $1 $SSID
				if [ $STATUS -eq 2 ]; then
					showGUIFn;
				elif [ $STATUS -eq 3 ]; then
					showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
				fi
			else
				showInterfaceCredentialsErrorDlg
				showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
			fi
		elif [ $CUSTOM -eq 1 ]; then
			showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
		else
			showWlanScanGUIFn "$1" "$2"
		fi
	else
		showInterfaceSSIDDlg "$SSID"
		if [ $? -eq 0 ]; then
			if [ ! -z "$RETURN" ]; then
				setInterfaceWlanCredentials "$1" "Open" "$RETURN"
				showInterfaceCredentialsSuccessDlg
				showRestartGUIFn $1 $SSID
				if [ $STATUS -eq 3 ]; then
					showGUIFn;
				elif [ $STATUS -eq 2 ]; then
					showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
				fi
			else
				showInterfaceCredentialsErrorDlg
				showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
			fi
		else
			showWlanProtectionGUIFn "$1" "$2" "$PROTECTION" "$CUSTOM"
		fi
	fi
}

function showRestartGUIFn() {
	showRestartAdapterDlg $1
	restartAdapterFn "$1"
	setAuto $1
	for i in $(seq 1 15); do
		showConnectingDlg "$2 ($1)"
		STATUS=$(showCMDFn progress $1)
		[ "$STATUS" -eq 2 ] || break
		sleep 2
	done

	if [ $STATUS -eq 1 ]; then
		showConnectionSuccessDlg "$2 ($1)"
	else
		showConnectionFailedDlg "$2 ($1)"
	fi
	return $STATUS;


}

# Executes the command line version of this module
# Arguments:
#  *
#    $1 Action [String]
#  list|status|dhcp|static|credentials|scan|restart|progress|type|connection
#    $2 Interface [String]
#  static
#    $3 IP [String]
#    $4 Netmask [String]
#    $5 Gateway [String]
#    $6 Nameserver 1 [String] (optional)
#    $7 Nameserver 2 [String] (optional)
#  credentials (No arguments return current settings)
#    $3 Encryption mode (WEP|WPA|Open) [string]
#    $4 ESSID
#    $5 WLANKEY (Only used for WEP|WPA)
# Returns:
#   0: Failure
#   1: Success
#   2: Connecting to wlan
# Echoes:
#   @0: Error code, see below
#   @1: What the user asked for
# Error codes:
#  -1: Wrong number of arguments
#  -2: Invalid argument
#  -3: No interfaces available
#  -4: Invalid interface
#  -5: Interface not configured
#  -6: Invalid IP
#  -7: Invalid netmask
#  -8: Invalid Gateway
#  -9: Invalid DNS
#  -10: Invalid wireless protection
#  -11: Already restarting
#  -12: Awaiting progress status
function showCMDFn() {
	case $1 in
		list)
			IFACES=$(listNetworkInterfacesFn)
			if [ -n "$IFACES" ]; then
				echo -e "$IFACES"
				return 1;
			else
				# No interfaces available
				echo "-3"
				return 0;
			fi
		;;
		status)
			# Check that we have 2 arguments ($1=action, $2=interface)
			if [ $# -eq 2 ]; then
				# No need to check for valid interface here as readNetworkConfigurationFn does it
				NETCONF=$(readNetworkConfigurationFn "$2")
				if [ $? -eq 1 ]; then
					if [ ! -z "$NETCONF" ]; then
						echo -e "$NETCONF"
						return 1;
					else
						echo "-5"
						return 0;
					fi
				else
					echo "-2"
					return 0;
				fi
			else
				# Wrong number of arguments
				echo "-1"
				return 0;
			fi
		;;
		dhcp)
			# Check that we have 3 arguments ($1=action, $2=interface)
			if [ $# -eq 2 ]; then
				# No need to check for valid interface here as setInterfaceDhcpFn does it
				setInterfaceDhcpFn "$2"
				if [ $? -eq 1 ]; then
					echo "1"
					setAuto "$2"
					return 1;
				else
					# Invalid interface
					echo "-2"
					return 0;
				fi
			else
				# Wrong number of arguments
				echo "-1"
				return 0;
			fi
		;;
		static)
			if [ $# -gt 3 ]; then
				# No need to check for valid interface here as setInterfaceStaticFn does it

				# $3 = IP
				# $4 = Netmask
				# $5 = Gateway
				# $6 = Nameserver1
				# $7 = Nameserver2
				# $8 = Method static/manual/disable

				# Handle optional name servers and method
				[ $# -gt 5 ] && NAMESERVER1="$6" || NAMESERVER1=""
				[ $# -gt 6 ] && NAMESERVER2="$7" || NAMESERVER2=""
				[ $# -gt 7 ] && METHOD="$8"      || METHOD=""

				# Validation of arguments is done inside this function
				RESULT=$(setInterfaceStaticFn "$2" "$3" "$4" "$5" "$NAMESERVER1" "$NAMESERVER2" "$METHOD"; echo $?)
				case $RESULT in
					0)
						# Invalid interface
						echo -2;
					;;
					1)
						[ "$METHOD" = disable ] || setAuto "$2"
						echo 1;
					;;
					3)
						echo -3;
					;;
					6)
						echo -6;
					;;
					7)
						echo -7;
					;;
					8)
						echo -8;
					;;
					9)
						echo -9;
					;;
				esac;
				# Return status of setInterfaceStaticFn
				return $RESULT;
			else
				# Wrong number of arguments
				echo "-1"
				return 0;
			fi
		;;
		credentials)
			if [ $# -gt 3 ]; then
				# No need to check for valid interface here as setInterfaceWlanCredentials does it

				# $2 = Interface
				# $3 = WPA|WEP|Open
				# $4 = ESSID
				# $5 = WLANKEY (semi-optional, only needed with WPA or WEP)

				WLANKEY=""
				if [ $# -gt 4 ]; then
					WLANKEY="$5"
				else
					case $3 in
						WPA|WEP)
							fetchWLANCredentialsFn "$3" "$(echo $4 | base64 -d)"
							echo "$WLANKEY"
							return 1
						;;
					esac
				fi

				RETURN=$(setInterfaceWlanCredentials "$2" "$3" "$(echo $4 | base64 -d)" "$(echo $WLANKEY | base64 -d)"; echo $?)
				case $RETURN in
					0)
						# Invalid interface
						echo -2;
					;;
					1)
						echo 1;
						setAuto $2
					;;
					2)
						echo -10;
					;;
				esac
				return $RETURN;
			else
				# Wrong number of arguments
				echo "-1"
				return 0;
			fi
		;;
		scan)
			if [ $# == 2 ] && [[ "$2" =~ "wlan" ]] || [[ "$2" =~ "ra" ]]; then
				isValidInterfaceFn "$2"
				if [ $? -eq 1 ]; then
					scanWLANNetworksFn $2;
					for WNETWORK in "${WNETWORKS[@]}"; do
						echo "$WNETWORK";
					done
				else
					# Invalid interface
					echo -2
				fi
			else
				# Wrong (number of) arguments
				echo -1
			fi
		;;
		restart)
			if [ $# == 2 ]; then
				isValidInterfaceFn "$2"
				if [ $? -eq 1 ]; then
					restartAdapterFn $2
					if [ "$?" -gt 0 ]; then
						setAuto $2
						echo 1
					else
						echo -11
					fi
				else
					echo -2;
				fi
			else
				echo -1
			fi
		;;
		progress)
			if [ -e /run/ifup.pid ] && kill -0 $(cat /run/ifup.pid) 2>/dev/null; then
				echo 2
			else
				getConnectStatusFn $2;
				if [ $STATUS -le 1 ]; then
					echo -12;
				elif [ $STATUS -eq 2 ]; then
					echo 1;
				elif [ $STATUS -eq 3 ]; then
					echo 0;
				fi

			fi
		;;
		type)
			if [ $# == 2 ]; then
				isValidInterfaceFn "$2"
				if [ $? -eq 1 ]; then
					getAdapterTypeFn $2;
					echo $?;
				else
					echo -2;
				fi
			else
				echo -1;
			fi
		;;
	esac
}
