#!/bin/bash
do {
	#////////////////////////////////////
	# DietPi
	#
	#////////////////////////////////////
	# Created by Daniel Knight / daniel.knight@dietpi.com / dietpi.com
	#////////////////////////////////////
	#
	# Info:
	# - Cleans "crap" on users system :)
	#
	# - Usage
	# /DietPi/dietpi/dietpi-cleaner no-input	= menu
	# /DietPi/dietpi/dietpi-cleaner 1 			= Run Enabled cleaners (no menu).
	# /DietPi/dietpi/dietpi-cleaner 2 			= Run All cleaners (no menu).
	#////////////////////////////////////

	#Grab Input (valid interger)
	setvar INPUT = '0'
	if [[ $1 =~ ^-?[0-9]+$ ]] {
		setvar INPUT = "$1"
	}

	#Import DietPi-Globals ---------------------------------------------------------------
	source /DietPi/dietpi/func/dietpi-globals
	G_CHECK_ROOT_USER
	G_CHECK_ROOTFS_RW
	export G_PROGRAM_NAME='DietPi-Cleaner'
	#Import DietPi-Globals ---------------------------------------------------------------

	#/////////////////////////////////////////////////////////////////////////////////////
	# Globals
	#/////////////////////////////////////////////////////////////////////////////////////
	setvar FP_TEMP = ""/tmp/.dietpi-cleaner""

	#/////////////////////////////////////////////////////////////////////////////////////
	# Banners
	#/////////////////////////////////////////////////////////////////////////////////////
	proc Banner_Cleaning {

		echo -e "\n\n"
		echo -e "\e[38;5;154m───────────────────────────────────────\e[0m\n\e[1mDietPi-Cleaner\e[0m\n - $INFO_CLEAN_NAME\n\e[38;5;154m───────────────────────────────────────\e[0m"

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Menu
	#/////////////////////////////////////////////////////////////////////////////////////
	#Whippy Whoopy Whiptail!
	setvar WHIP_BACKTITLE = ''- DietPi-Cleaner -''
	setvar WHIP_TITLE = "$WHIP_BACKTITLE"
	setvar WHIP_QUESTION = '0'
	setvar CHOICE = '0'
	setvar TARGETMENUID = '0'

	proc Menu_Exit {
			setvar WHIP_TITLE = ''Exit DietPi-Cleaner?''
			setvar WHIP_QUESTION = ''Exit DietPi-Cleaner?''
			whiptail --title $WHIP_TITLE --yesno $WHIP_QUESTION --backtitle $WHIP_TITLE --yes-button "Ok" --no-button "Back" --defaultno 9 55
			setvar CHOICE = ""$?
			if (( $CHOICE == 0 )) {
				#exit
				setvar TARGETMENUID = '-1'
			} else {
				#Return to Main Menu
				setvar TARGETMENUID = '0'
			}
	}

	#TARGETMENUID=0
	proc Menu_Main {

		setvar WHIP_TITLE = "$WHIP_BACKTITLE"

		#Get current RootFS usage
		Update_Space_Used

		setvar TARGETMENUID = '0'
		setvar WHIP_QUESTION = ""Free up used space and system resources:\n - RootFS usage current = $ROOT_SPACE_USED_CURRENT MB\n - RootFS space cleared = $ROOT_SPACE_FREE_DELTA MB""

		setvar OPTION = $(whiptail --title "$WHIP_TITLE" --backtitle "$WHIP_BACKTITLE" --menu "$WHIP_QUESTION" --cancel-button "Exit" 15 75 5 \
		"Help" "What does DietPi-Cleaner do?" \
		"Cleaners" "Control which cleaners are enabled." \
		" - Files" "Set file cleaner options." \
		"Test" "Simulate the cleaning process, without modifying any data." \
		"Run" "Run enabled cleaners." 3>&1 1>&2 2>&3)

		setvar CHOICE = ""$?
		if (( $CHOICE == 0 )) {
			case (OPTION) {
				Help {
					whiptail --title "DietPi-Cleaner Help" --msgbox "DietPi-Cleaner is a program that allows you to remove unwanted junk from your DietPi system, freeing up filesystem space in the process.\n\nSimply enable the cleaners you require, then select Test to see what will happen, without modifying your system.\nOnce your satisfied with the Test results, select Run to clean your system.\n\nMore information:\n - http://dietpi.com/phpbb/viewtopic.php?f=8&t=5&p=623#p623" --backtitle $WHIP_BACKTITLE 16 75
				}
				" - Files" {
					setvar TARGETMENUID = '2'
				}
				Cleaners {
					setvar TARGETMENUID = '1'
				}
				Test {
					#Enable test
					setvar DRY_RUN = '1'
					#check for at least 1 enabled.
					local at_least_one_cleaner_is_enabled=0
					for ((i=0; i<$MAX_CLEANERS; i++))
					do
						if (( ${aEnabledCleaners[$i]} == 1 )); then
							at_least_one_cleaner_is_enabled=1
							break
						fi
					done

					if (( $at_least_one_cleaner_is_enabled == 1 )) {
						#Yes/No
						whiptail --title "Run DietPi-Cleaner?" --yesno "DietPi-Cleaner will now simulate your enabled cleaners.\n\n(Notice): No data will be modified.\n\nContinue with test run?" --backtitle $WHIP_BACKTITLE --defaultno 12 70
						setvar CHOICE = ""$?
						if (( $CHOICE == 0 )) {
							Run_Cleaners
						}
					} else {
						whiptail --title "No cleaner jobs enabled" --msgbox "DietPi-Cleaner could not be run as there are no enabled cleaners. Please go to cleaners, then select which you would like to enable." 10 70
					}
				}
				Run {
					#Disable test
					setvar DRY_RUN = '0'
					#check for at least 1 enabled.
					local at_least_one_cleaner_is_enabled=0
					for ((i=0; i<$MAX_CLEANERS; i++))
					do
						if (( ${aEnabledCleaners[$i]} == 1 )); then
							at_least_one_cleaner_is_enabled=1
							break
						fi
					done

					if (( $at_least_one_cleaner_is_enabled == 1 )) {
						#Yes/No
						whiptail --title "Run DietPi-Cleaner?" --yesno "DietPi-Cleaner will now run your enabled cleaners.\n\n(Notice): If you are unsure what this program will do, I would recommend creating a backup with dietpi-backup before proceeding.\n\nWould you like to continue and start the cleaning process?" --backtitle $WHIP_BACKTITLE --defaultno 13 70
						setvar CHOICE = ""$?
						if (( $CHOICE == 0 )) {
							Run_Cleaners
						}
					} else {
						whiptail --title "No cleaner jobs enabled" --msgbox "DietPi-Cleaner could not be run as there are no enabled cleaners. Please go to cleaners, then select which you would like to enable." 10 70
					}
				}
			}
		} else {
			Menu_Exit
		}

	}

	#TARGETMENUID=1
	proc Menu_Cleaners {

		#Return to main menu
		setvar TARGETMENUID = '0'

		#Get on/off whilptail status
		local aWhiptailLine=()
		local OnOff_Status="on"
		for ((i=0; i<$MAX_CLEANERS; i++))
		do
			#On/Off status
			OnOff_Status="on"
			if (( ${aEnabledCleaners[$i]} == 0 )); then
				OnOff_Status="off"
			fi

			#Define options
			if (( $i == 0 )); then
				aWhiptailLine+=("$i " "Dev - Uninstalls all dev packages (eg: git, lib123-dev)." "$OnOff_Status")
			elif (( $i == 1 )); then
				aWhiptailLine+=("$i " "Manpages - Removes offline documentation." "$OnOff_Status")
			elif (( $i == 2 )); then
				aWhiptailLine+=("$i " "Files - Scan and remove files matching user include list." "$OnOff_Status")
			elif (( $i == 3 )); then
				aWhiptailLine+=("$i " "Logs - Clears the log file directory (/var/log)." "$OnOff_Status")
			elif (( $i == 4 )); then
				aWhiptailLine+=("$i " "Apt - Clears the apt cache and runs a fresh update." "$OnOff_Status")
			else
				aWhiptailLine+=("New " "Unknown" "$OnOff_Status")
			fi

		done

		setvar WHIP_TITLE = ''- Options : Cleaner Selection -''
		setvar WHIP_QUESTION = ''Please use the spacebar to toggle which cleaners are enabled.''
		whiptail --title $WHIP_TITLE --checklist $WHIP_QUESTION --backtitle $WHIP_TITLE --separate-output 14 75 5 ${aWhiptailLine[@]} 2> "$FP_TEMP"
		setvar CHOICE = ""$?

		if (( $CHOICE == 0 )) {

			for ((i=0; i<$MAX_CLEANERS; i++))
			do
				aEnabledCleaners[$i]=0
				if (( $(cat "$FP_TEMP" | grep -ci -m1 "$i ") == 1 )); then
					aEnabledCleaners[$i]=1
				fi

			done

		}

		#Clean up temp files
		rm $FP_TEMP &> /dev/null

		#Delete[] array
		unset aWhiptailLine

	}

	#TARGETMENUID=2
	proc Menu_Options_Files {

		#Return to main menu
		setvar TARGETMENUID = '0'

		local option_1_text="Include mount directory (/mnt/*) during file scan"
		local include_mnt_status="Disabled"
		if (( $INCLUDE_MNT == 1 )) {
			setvar include_mnt_status = ""Enabled""
		}

		local option_2_text="Modify filenames/extensions to include during scan."

		setvar WHIP_QUESTION = ""Files: Cleaner options.\n(NB) The cleaner named 'Files' must be enabled for this to work.""
		setvar WHIP_TITLE = ''- Files: Cleaner options -''

		setvar OPTION = $(whiptail --title "$WHIP_TITLE" --backtitle "$WHIP_BACKTITLE" --menu "$WHIP_QUESTION" --cancel-button "Exit" 12 68 2 \
		"$option_1_text" ": $include_mnt_status" \
		"$option_2_text" "" 3>&1 1>&2 2>&3)

		setvar CHOICE = ""$?
		if (( $CHOICE == 0 )) {
			case (OPTION) {
				"$option_1_text" {
					if (( $INCLUDE_MNT == 1 )) {
						setvar INCLUDE_MNT = '0'
					} else {
						setvar INCLUDE_MNT = '1'
					}
					setvar TARGETMENUID = '2'
				}
				"$option_2_text" {
					nano $FILEPATH_CUSTOMFILES
					setvar TARGETMENUID = '2'
				}
			}
		}

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Cleaner stats
	#/////////////////////////////////////////////////////////////////////////////////////
	# Space free after running cleaner
	setvar ROOT_SPACE_USED_BEFORE = '0'
	setvar ROOT_SPACE_USED_AFTER = '0'
	setvar ROOT_SPACE_USED_CURRENT = '0'
	setvar ROOT_SPACE_FREE_DELTA = ""Cleaner has not been run - 0""
	setvar ROOTFS_DEVICE_PATH = $(sed -n 4p /DietPi/dietpi/.hw_model)

	proc Update_Space_Used {

		setvar ROOT_SPACE_USED_CURRENT = $(df --block-size MB | grep "$ROOTFS_DEVICE_PATH" | awk '{ print $3 }' | tr -d 'MB')
	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Cleaner Funcs
	#/////////////////////////////////////////////////////////////////////////////////////
	setvar MAX_CLEANERS = '5'
	setvar aEnabledCleaners = ''()
	for ((i=0; i<$MAX_CLEANERS; i++))
	do
		aEnabledCleaners[$i]=0
	done

	setvar INCLUDE_MNT = '0'
	setvar DRY_RUN = '0'

	setvar INFO_CLEAN_NAME = """"

	proc Run_Cleaners {

		#stop services
		/DietPi/dietpi/dietpi-services stop

		Update_Space_Used
		setvar ROOT_SPACE_USED_BEFORE = "$ROOT_SPACE_USED_CURRENT"

		#Run enabled cleaners
		for ((i=0; i<$MAX_CLEANERS; i++))
		do
			if (( ${aEnabledCleaners[$i]} == 1 )); then
				Run_Cleaner_"$i"
			fi
		done

		Update_Space_Used
		setvar ROOT_SPACE_USED_AFTER = "$ROOT_SPACE_USED_CURRENT"

		#start services
		/DietPi/dietpi/dietpi-services start

		#inform user of space cleared.
		setvar ROOT_SPACE_FREE_DELTA = $(( $ROOT_SPACE_USED_BEFORE - $ROOT_SPACE_USED_AFTER ))

		setvar WHIP_QUESTION = ""DietPi-Cleaner has finished cleaning RootFS:\n - $ROOT_SPACE_FREE_DELTA MB of space has been cleared.""
		if (( $INPUT == 0 )) {
			whiptail --title "DietPi-Cleaner completed." --msgbox $WHIP_QUESTION 10 70
		} elif (( $INPUT == 1 )) {
			echo -e "\n$WHIP_QUESTION\n"
		}

	}

	# Dev Packages
	proc Run_Cleaner_0 {

		setvar INFO_CLEAN_NAME = ""Dev packages""
		Banner_Cleaning

		local string_package_names=""
		while read line
		{
			#Convert lined list into a 1 line string.
			setvar string_package_names = ""$line ""

		} < <(dpkg -l | grep '\-dev:' | awk '{ print $2 }' | cut -f1 -d":")

		#add other dev packages
		setvar string_package_names = ""build-essential git""

		#Purge
		local Yes_or_Simulate="-y"
		if (( $DRY_RUN == 1 )) {
			setvar Yes_or_Simulate = ""-s""
		}

		apt-get purge $string_package_names $Yes_or_Simulate
		apt-get autoremove --purge $Yes_or_Simulate

		#Update DietPi .installed
		if (( $DRY_RUN == 0 )) {
			sed -i "/BUILDESSENTIAL=/c\BUILDESSENTIAL=0" /DietPi/dietpi/.installed
			sed -i "/GITCLIENT=/c\GITCLIENT=0" /DietPi/dietpi/.installed
		}

	}

	# Man pages / doc
	proc Run_Cleaner_1 {

		setvar INFO_CLEAN_NAME = ""Man pages and docs""
		Banner_Cleaning

		local Yes_or_Simulate="-y"
		if (( $DRY_RUN == 1 )) {
			setvar Yes_or_Simulate = ""-s""
		}

		apt-get purge man manpages $Yes_or_Simulate
		apt-get autoremove --purge $Yes_or_Simulate

		#Remove files
		if (( $DRY_RUN == 0 )) {
			rm -R /usr/share/man
			rm -R /usr/share/doc
			rm -R /usr/share/doc-base
		}

	}

	# Files
	proc Run_Cleaner_2 {

		setvar INFO_CLEAN_NAME = ""Files""
		Banner_Cleaning

		#generate list of files to include. Remove lines with (#) or (space) or (empty) from list
		cat $FILEPATH_CUSTOMFILES | sed '/#/d' | sed '/ /d' | sed '/^$/d' > "$FP_TEMP"

		#Check include file has at least one value/line to process.
		local line_count=$(cat "$FP_TEMP" | wc -l)
		if (( $line_count == 0 )) {

			echo -e "\nNo files to find. Have you setup the Files options and added filename entries to match?\n"

		} else {

			#Create array to hold user includes
			local aCustomFiles=()
			readarray aCustomFiles < "$FP_TEMP"

			#Generate the find string
			local find_string=""
			echo -e "\nSearching for filenames matching:"
			for ((i=0; i<${#aCustomFiles[@]}; i++))
			do
				echo -e "- ${aCustomFiles[$i]}"

				if (( $i == 0 )); then
					find_string="-name ${aCustomFiles[$i]}"
				else
					find_string+=" -or -name ${aCustomFiles[$i]}"
				fi

			done

			echo -e "Please wait...."

			#Find all matching filenames.
			find / -type f $find_string > "$FP_TEMP"

			#Remove /mnt from find list
			if (( $INCLUDE_MNT == 0 )) {
				sed -i '/\/mnt/d' $FP_TEMP
			}

			setvar line_count = $(cat "$FP_TEMP" | wc -l)
			if (( $line_count == 0 )) {
				echo -e "\nNo matching filenames were found.\n"
			} else {
				echo -e "\nFound the following matching files:\n"
			}

			#Remove files
			while read line
			{
				echo -e "- Filepath: $line"
				if (( $DRY_RUN == 0 )) {
					echo -e "Deleted.\n"
					rm $line
				}

			} < "$FP_TEMP"

			#delete[]
			unset aCustomFiles

		}

		rm $FP_TEMP &> /dev/null

	}

	# Logs
	proc Run_Cleaner_3 {

		setvar INFO_CLEAN_NAME = ""Log files""
		Banner_Cleaning

		if (( $DRY_RUN == 0 )) {
			/DietPi/dietpi/dietpi-logclear 1
		}

	}

	# Apt caches
	proc Run_Cleaner_4 {

		setvar INFO_CLEAN_NAME = ""Apt cache and update""
		Banner_Cleaning

		if (( $DRY_RUN == 0 )) {

			apt-get clean
			rm /var/lib/apt/lists/* -vf
			G_AGUP

		}

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	# Settings File
	#/////////////////////////////////////////////////////////////////////////////////////
	#Define Location
	setvar FILEPATH_SETTINGS = ""/DietPi/dietpi/.dietpi-cleaner""
	setvar FILEPATH_CUSTOMFILES = ""/DietPi/dietpi/.dietpi-cleaner_custom_files""

	proc Read_Settings_File {

		if test -f $FILEPATH_SETTINGS {

			#Get line count
			local line_count=$(cat "$FILEPATH_SETTINGS" | wc -l)

			#Load settings
			for ((i=0; i<$line_count; i++))
			do
				aEnabledCleaners[$i]=$(sed -n $(( $i + 1 ))p $FILEPATH_SETTINGS)
			done

		}

		#Custom filescan options
		if test ! -f $FILEPATH_CUSTOMFILES {
			cat <<< """ > "$FILEPATH_CUSTOMFILES"
# ------------------------------------------------------------------
# Specify filenames or extentions to match during filescan removals.
#
# One item per line.
#
# Examples:
# *.tmp
# ThisFileWillBeDeleted.mp3
# *AnyFilenameContainingThisTextWillBeDeleted*
#
# To save and exit:
# - Press CTRL+X
# - Press Y
# - Press Enter
# ------------------------------------------------------------------
# Uncomment line below to include temp files during scan.
#*.tmp

# Uncomment line below to include Windows Thumbnail cache during scan.
#Thumbs.db
"""
> "$FILEPATH_CUSTOMFILES"
# ------------------------------------------------------------------
# Specify filenames or extentions to match during filescan removals.
#
# One item per line.
#
# Examples:
# *.tmp
# ThisFileWillBeDeleted.mp3
# *AnyFilenameContainingThisTextWillBeDeleted*
#
# To save and exit:
# - Press CTRL+X
# - Press Y
# - Press Enter
# ------------------------------------------------------------------
# Uncomment line below to include temp files during scan.
#*.tmp

# Uncomment line below to include Windows Thumbnail cache during scan.
#Thumbs.db
_EOF_
		}

	}

	proc Write_Settings_File {

		#Enabled/Disabled Cleaner Settings
		rm $FILEPATH_SETTINGS &> /dev/null
		for ((i=0; i<$MAX_CLEANERS; i++))
		do
			echo -e "${aEnabledCleaners[$i]}" >> $FILEPATH_SETTINGS
		done

	}

	#/////////////////////////////////////////////////////////////////////////////////////
	#Main
	#/////////////////////////////////////////////////////////////////////////////////////
	Read_Settings_File
	#-----------------------------------------------------------------------------------
	#Run Menu
	if (( $INPUT == 0 )) { {

			clear

			if (( $TARGETMENUID == 0 )) {
				Menu_Main
			} elif (( $TARGETMENUID == 1 )) {
				Menu_Cleaners
			} elif (( $TARGETMENUID == 2 )) {
				Menu_Options_Files
			}

		}

		Write_Settings_File

	#-----------------------------------------------------------------------------------
	#Run Enabled cleaners (no menu)
	} elif (( $INPUT == 1 )) {

		Run_Cleaners

	#-----------------------------------------------------------------------------------
	#Run ALL cleaners (no menu)
	} elif (( $INPUT == 2 )) {

		for ((i=0; i<$MAX_CLEANERS; i++))
		do
			aEnabledCleaners[$i]=1
		done

		Run_Cleaners

	}
	#-----------------------------------------------------------------------------------
	#delete[]
	unset aEnabledCleaners
	#-----------------------------------------------------------------------------------
	exit
	#-----------------------------------------------------------------------------------
}