#!/bin/bash
#
#Copyright 2012 - 2018 CurlyMo & 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          |
#|------------------------------------|

# The arguments this module accepts
ARGUMENTS=(select update values list);

declare -A OCSETTINGS

arch=$(xbian-arch revision)
OCSCHMOO=1200

case "$arch" in
    imx6)
	grep -q 'overclock=.' /boot/boot.scr.txt || sed -i 's/setenv customcmdline /setenv customcmdline overclock=0 /' /boot/boot.scr.txt
	# Names of the overclock settings
	OCNAMES=(iMX6:None iMX6:High);

	# Values of the overclock settings
	OCSETTINGS[0]="996 n/a n/a n/a"
	OCSETTINGS[1]="1200 n/a n/a n/a"

	# Define the (possible) dangerous overclock settings
	OCDANGEROUS=()
	;;
    rpi)
	# Names of the overclock settings
	OCNAMES=(Pi:None Pi:Modest Pi:XBian Pi:Medium Pi:High Pi:Turbo);

	# Values of the overclock settings
	OCSETTINGS[0]="700 250 400 0";
	OCSETTINGS[1]="800 250 400 0";
	OCSETTINGS[2]="840 320 400 0";
	OCSETTINGS[3]="900 333 450 0";
	OCSETTINGS[4]="950 450 500 2";
	OCSETTINGS[5]="1000 500 500 6";

	# Define the (possible) dangerous overclock settings
	OCDANGEROUS=(Pi:Turbo)
	;;
    rpi2)
	# Names of the overclock settings
	OCNAMES=(Pi2:None Pi2:High);

	# Values of the overclock settings
	OCSETTINGS[0]="900 250 450 0";
	OCSETTINGS[1]="1000 500 450 2";

	# Define the (possible) dangerous overclock settings
	OCDANGEROUS=()
	;;
    rpi3)
	if command -v rpi_revision >/dev/null && rpi_revision | grep -q "Model B Pi 3+"; then
	    # Names of the overclock settings
	    OCNAMES=(Pi3B+:None Pi3B+:XBian Pi3B+:Turbo);

	    # Values of the overclock settings
	    OCSETTINGS[0]="1400 400 500 0";
	    OCSETTINGS[1]="... ... 450 ...";
	    OCSETTINGS[2]="1500 500 450 2";

	    # Define the (possible) dangerous overclock settings
	    OCDANGEROUS=(Pi3B+:Turbo)
	    OCSCHMOO=1400
	else
	    # Names of the overclock settings
	    OCNAMES=(Pi3:None Pi3:Turbo);

	    # Values of the overclock settings
	    OCSETTINGS[0]="1200 400 450 0";
	    OCSETTINGS[1]="1300 500 450 2";

	    # Define the (possible) dangerous overclock settings
	    OCDANGEROUS=(Pi3:Turbo)
	fi

	;;
    rpi0)
	# Names of the overclock settings
	OCNAMES=(PiZero:None);

	# Values of the overclock settings
	OCSETTINGS[0]="1000 400 450 0";

	# Define the (possible) dangerous overclock settings
	OCDANGEROUS=()
	;;
    rpi0w)
	# Names of the overclock settings
	OCNAMES=(PiZeroW:None);

	# Values of the overclock settings
	OCSETTINGS[0]="1000 400 450 0";

	# Define the (possible) dangerous overclock settings
	OCDANGEROUS=()
	;;
    *)
	OCNAMES=(Unknown);

	# Values of the overclock settings
	OCSETTINGS[0]="1000 400 400 0";

	# Define the (possible) dangerous overclock settings
	OCDANGEROUS=()
	;;
esac

# Define the safe overclock settings
OCSAFE=(Pi:None Pi:Modest Pi:XBian Pi2:None Pi3:None Pi3B+:XBian PiZero:None PiZeroW:None iMX6:None)

# Did we already show the warning
OCWARNING=0;

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

source $BASEPATH/modules/overclocking/functions
if [ $GUIMODE -eq 1 ]; then
	source $BASEPATH/modules/overclocking/dialogs
fi
source $BASEPATH/functions/config
#|------------------------------------|
#|           Main program             |
#|------------------------------------|

# Executes the GUI version of this module
function showGUIFn() {
	if [ $OCWARNING -eq 0 ]; then
		showOCWarningDlg;
		OCWARNING=1;
	fi
	showLoadingDlg;
	getCurrentOCSettingsFn;
	createOCDLGMenuFn $CURRENTOC;
	m="$(_ overclocking.label.preset)"
	exp=$((${#m}-8)); (( $exp < 0 )) && exp=0
	ODW=$DEFAULTWIDTH; DEFAULTWIDTH=$((DEFAULTWIDTH+exp))
	showOCSettingsDlg $OCMENU;
	rc=$?
	DEFAULTWIDTH=$ODW
	if [ $rc -eq 0 ]; then
		if [ $RETURN -eq $(($CURRENTOC+1)) ]; then
			showNoOCChangeDlg;
			showGUIFn;
		elif [ $RETURN -eq $((${#OCSETTINGS[@]}+1)) ]; then
			if [ $CURRENTOC -eq -1 ]; then
				SETTINGS="${OCOLDSETTINGS[@]}";
			else
				SETTINGS=(${OCSETTINGS[$CURRENTOC]});
			fi
			showCustomOCDlg "${SETTINGS[@]}";
			if [ $? -eq 0 ]; then
				IFS=$'\n';
				VALUES=($RETURN);
				NEWSETTINGS[0]=${VALUES[0]};
				NEWSETTINGS[1]=${VALUES[2]};
				NEWSETTINGS[2]=${VALUES[4]};
				NEWSETTINGS[3]=${VALUES[6]};
				if [ "${NEWSETTINGS[0]} ${NEWSETTINGS[1]} ${NEWSETTINGS[2]} ${NEWSETTINGS[3]}" ==  "${SETTINGS[*]}" ]; then
					showNoOCChangeDlg;
				elif [ ${#NEWSETTINGS[@]} -eq 4 ]; then
					updateCustomOCSettingsFn "${NEWSETTINGS[*]}";
					if [ $? -eq 1 ]; then
						showUpdatedOCDlg;
						askForRebootFn;
						showGUIFn;
					else
						showErrorDlg;
					fi
				else
					showOCEmptyFieldsDlg;
					showGUIFn;
				fi
			else
				showGUIFn;
			fi
		else
			updateOCSettingsFn $(($RETURN-1));
			if [ $? -eq 1 ]; then
				showUpdatedOCDlg;
				askForRebootFn;
				showGUIFn;
			else
				showErrorDlg;
			fi
		fi
	fi
}

# Executes the command line version of this module
#  $1 Argument [String]
#  $2 Overclock preset name [String] (Update|Values)
#  $3 ARM [Integer] (Update)
#  $4 CORE [Integer] (Update)
#  $5 SDRAM [Integer] (Update)
#  $6 VOLTAGE [Integer] (Update)
# Returns
#  *Select [String] The current overclock preset name or 'Custom'
#  *Update [Integer] Set the overclock to a preset or use custom values
#   -  1 Success
#   -  0 Failure 
#   - -1 Preset does not exist
#   - -2 Not enough arguments
#	- -3 Non-numeric arguments
#  *Values [String] List of current values seperated by spaces or the values of a preset
#   - $ARM [Integer]
#   - $CORE [Integer]
#   - $SDRAM [Integer]
#   - $VOLTAGE [Integer]
#  *List [String] A space seperated list of all presets available
#   - * [String]
function showCMDFn() {
	case $1 in
		"select")
			getCurrentOCSettingsFn;
			if [ $CURRENTOC -eq -1 ]; then
				echo "custom"
			else
				echo ${OCNAMES[$CURRENTOC],,}
			fi
		;;
		"update")
			shift;
			if [ "${1,,}" == "custom" ]; then
				shift
				if [ $# -eq 4 ]; then
					NEWSETTINGS=($@);
					updateCustomOCSettingsFn "${NEWSETTINGS[*]}"
					RETURN=$?;
					if [ $RETURN -eq 1 ]; then
						echo 1;
						askForRebootFn;
					elif [ $RETURN -eq 2 ]; then
						echo -3;
					else
						echo 0;
					fi
				else
					echo -2;
				fi
			else
				if [ ! -z $(echo ${OCNAMES[*]} | grep -o -i $1) ]; then
					MATCH=0;
					for KEY in ${!OCNAMES[@]}; do
						if [ ${OCNAMES[$KEY],,} == $1 ]; then
							MATCH=1;
							updateOCSettingsFn $KEY;
							RETURN=$?
							if [ $RETURN -eq 1 ]; then
								askForRebootFn;
								echo 1;
							elif [ $RETURN -eq 2 ]; then
								echo -3;
							else
								echo 0;
							fi
						fi
					done
					if [ $MATCH -eq 0 ]; then
						echo -1
					fi
				else
					echo -1;
				fi
			fi
		;;
		"values")
			shift;
			if [ $# -eq 0 ]; then
				getCurrentOCSettingsFn;
				if [ $CURRENTOC -eq -1 ]; then
					echo ${OCOLDSETTINGS[*]};
				else
					echo ${OCSETTINGS[$CURRENTOC]};
				fi
			else
				if [ ! -z $(echo ${OCNAMES[*]} | grep -o -i $1) ]; then
					for KEY in ${!OCNAMES[@]}; do
						if [ ${OCNAMES[$KEY],,} == $1 ]; then
							echo ${OCSETTINGS[$KEY]}
						fi
					done
				else
					echo -1;
				fi
			fi
		;;
		"list")
			for NAME in ${OCNAMES[@]}; do
				echo $NAME;
			done;
			test $(xbian-arch) != iMX6 || return 0
			echo "Custom"
		;;
	esac 
}
