#!/bin/bash
# Maintained by Sean Kilgarriff and Killian Brackey at ZZROT Design
#
# The MIT License (MIT)
# Copyright © 2016 ZZROT LLC <docker@zzrot.com>
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the “Software”), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#

#ENVIRONMENT VARIABLES

# @info:	Docker-clean current version
declare VERSION="2.0.4"

# @info:	Required Docker version for Volume functionality
declare REQUIRED_VERSION="1.9.0"

# @info:	Required version for docker network inspect filters
declare NETWORK_REQUIRED_VERSION="1.10.0"

# @info:	Boolean for determining which network cleaning function to use
declare HAS_NETWORK_VERSION=false

# @info:	Boolean for storing Docker version info
declare HAS_VERSION=false

# @info:	Boolean for verbose mode
declare VERBOSE=false

# @info:	Boolean for dry run to see before removing
declare DRY_RUN=false

# @info:    Boolean to flag if Containers should be stopped.
declare STOP_CONTAINERS=false

# @info:	Boolean to flag if containers should be deleted.
declare CLEAN_CONTAINERS=false

# @info:	Boolean to flag if images should be deleted.
declare CLEAN_IMAGES=false

# @info:	Boolean to flag if volumes should be deleted.
declare CLEAN_VOLUMES=false

# @info:	Boolean to flag if networks should be deleted.
declare CLEAN_NETWORKS=false

# @info:	Boolean to flag if machine/daemon should be reset.
declare RESTART=false

# @info:    Boolean to flag if tagged images are to be deleted.
declare DELETE_TAGGED=false

# @info:    Boolean to flag if Containers with status Created will be deleted or not.
declare DELETE_CREATED=true

# @info:	Global arrays of objects that would be deleted, used for dry run accuracy.
declare -a CONTAINERS_TO_DELETE	# Currently in use
declare -a IMAGES_IN_USE			# Currently in use
declare -a IMAGES_TO_DELETE			# Currently in use
declare -a REMAINING_CONTAINERS		# Currently in use
declare -a EMPTY_NETWORKS			# Currently in use
#declare -a VOLUMES_TO_DELETE		# Not in use

# @info:	Docker host to use (default to empty or localhost).
declare DOCKER_HOST

#FUNCTIONS

# @info:  Overrides the system docker daemon so we can pass in a host
# @args:	Global Arguments $@
function docker(){
	if [ -z "$DOCKER_HOST" ]; then
		command "docker" "$@"
	else
		command "docker" -H "$DOCKER_HOST" "$@"
	fi
}

# @info:    Parses and validates the CLI arguments
# @args:	Global Arguments $@
# TODO: handle use case where just -n or just -l flag is given
function parseCli(){
	if [[ "$#" -eq 0 ]]; then
		#CLEAN_CONTAINERS=false 		# changed to false so doesn't exit containers
		CLEAN_IMAGES=true
		CLEAN_VOLUMES=true
		CLEAN_NETWORKS=true
		dockerClean
	fi
	if [[ "$#" -gt 0 ]]; then
		#If there is only one flag, and it is dry run or log, set defaults
		key="$1"
		case $key in
			-n | --dry-run) CLEAN_IMAGES=true; CLEAN_VOLUMES=true; CLEAN_NETWORKS=true ;;
			-l | --log) CLEAN_IMAGES=true; CLEAN_VOLUMES=true; CLEAN_NETWORKS=true ;;
		esac
	while [[ "$#" -gt 0 ]]; do
		key="$1"
		val="$2"
		case $key in
			stop ) STOP_CONTAINERS=true; CLEAN_CONTAINERS=true; CLEAN_IMAGES=true; CLEAN_VOLUMES=true; CLEAN_NETWORKS=true ;;
			images ) DELETE_TAGGED=true; CLEAN_CONTAINERS=true; CLEAN_IMAGES=true; CLEAN_VOLUMES=true; CLEAN_NETWORKS=true ;;
			run ) CLEAN_CONTAINERS=true; CLEAN_IMAGES=true; CLEAN_VOLUMES=true; CLEAN_NETWORKS=true ;;
			all ) STOP_CONTAINERS=true; DELETE_TAGGED=true; CLEAN_CONTAINERS=true; CLEAN_IMAGES=true; CLEAN_VOLUMES=true; CLEAN_NETWORKS=true ;;
			-H | --host) DOCKER_HOST=$val; shift;;
			-s | --stop) STOP_CONTAINERS=true ;;
			-n | --dry-run) DRY_RUN=true ;;
			-l | --log) VERBOSE=true ;;
			-c | --containers) CLEAN_CONTAINERS=true ;;
			-i | --images) CLEAN_IMAGES=true ;;
			-m | --volumes) CLEAN_VOLUMES=true ;;
			-net | --networks) CLEAN_NETWORKS=true ;;
			-r | --restart) RESTART=true ;;
			-d | --created) DELETE_CREATED=false ;;
			-t | --tagged) DELETE_TAGGED=true ;;
			-a | --all) STOP_CONTAINERS=true; DELETE_TAGGED=true; CLEAN_CONTAINERS=true; CLEAN_IMAGES=true; CLEAN_VOLUMES=true; CLEAN_NETWORKS=true; RESTART=true ;;
			-v | --version) version; exit 0 ;;
			-h | --help | *) usage; exit 0 ;;
		esac
		shift
	done
	dockerClean
fi
}

# @info:	Prints out Docker-clean current version
function version {
	echo $VERSION
}

# @info:	Prints out usage
function usage {
	echo
	echo "  Docker Clean Usage Options: "
	echo "-------------------------------"
	echo
  	echo "-h or --help        Opens this help menu"
  	echo "-v or --version     Prints the current docker-clean version"
  	echo
	echo " Running without any options will remove dangling volumes and untagged images only."
	echo " All of the options are option, and while they overlap they can all be run concurrently."
	echo " NOTE: By default, created containers will always be included, see -d, --created."
	echo
	echo "stop         Stops and removes all containers, cleans dangling volumes, and networks"
	echo
	echo "images       Removes all tagged and untagged images, stopped containers, "
	echo "             dangling volumes, and networks"
	echo
	echo "run          Removes all stopped containers, untagged images, dangling volumes, and networks"
	echo
	echo "all          Stops and removes all containers, images, volumes and networks"
	echo
	echo "Additional Flag options:"
	echo
	echo "-H   or --host        Specifies the docker host to run against"
	echo "                      Useful for docker swarm maintenance"
	echo "                      ie: -H 127.0.0.1:4000"
	echo
	echo "-n   or --dry-run     Adding this additional flag will list items to be"
	echo "                      removed without executing any stopping or removing commands"
	echo
	echo "-s   or --stop        Stops all running containers"
	echo
  	echo "-c   or --containers  Removes all stopped containers"
	echo
  	echo "-i   or --images      Removes all untagged images"
	echo
  	echo "-net or --networks    Removes all empty Networks (all network cleans are only empty)"
	echo
	echo "-r   or --restart     Restarts the docker machine/daemon"
	echo
	echo "-d   or --created     By default, CREATED containers are set to be removed.  Adding this"
	echo "                      flag will ensure that all created containers are not cleaned"
	echo
	echo "-t   or --tagged      Removes all tagged images"
	echo
	echo "-a   or --all         Stops and removes all Containers, Images, AND Restarts docker"
	echo
	echo "-l   or --log         Adding this as an additional flag will list all"
	echo "                      image, volume, and container deleting output"


}

# @info:	Prints out 3-point version (000.000.000) without decimals for comparison
# @args:	Docker Version of the client
function printVersion {
	echo "$@" | awk -F. '{ printf("%03d%03d%03d\n", $1,$2,$3); }';
}

# @info:	Checks Docker Version and then configures the HAS_VERSION var.
function checkVersion  {
	local Docker_Version
	Docker_Version="$(docker --version | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')"
	if [ "$(printVersion "$Docker_Version")" -gt "$(printVersion "$REQUIRED_VERSION")" ]; then
		HAS_VERSION=true
    else
        echo "Your Version of Docker is below 1.9.0 which is required for full functionality."
        echo "Please upgrade your Docker daemon. Until then, the Volume and Network processing will not work."
    fi
}

# @info:	Checks if network inspect filters are compatible
function checkNetworkVersion {
	local Docker_Version
	Docker_Version="$(docker --version | sed 's/[^0-9.]*\([0-9.]*\).*/\1/')"
	if [ "$(printVersion "$Docker_Version")" -gt "$(printVersion "$NETWORK_REQUIRED_VERSION")" ]; then
		echo true
	fi
}

# @info:	Checks to see if Docker is installed and connected
function checkDocker {
    #Run Docker ps to make sure that docker is installed
    #As well as that the Daemon is connected.
    docker ps &>/dev/null
    DOCKER_CHECK=$?

    #If Docker Check returns 1 (Error), send a message and exit.
	if [ ! "$DOCKER_CHECK" ]; then
        echo "Docker is either not installed, or the Docker Daemon is not currently connected."
        echo "Please check your installation and try again."
        exit 1;
    fi
}

# @info: Stops all running docker containers.
function stop {
	IFS=$'\n' read -rd '' -a runningContainers <<<"$(docker ps -q)"
	if $DRY_RUN; then
		echo "Dry run on stoppage of running containers:"
		if [[ ! $runningContainers ]]; then
			echo "No running containers. Running without -n or --dry-run flag won't stop any containers."
            echo #Spacing
		else
			echo "Running without -n or --dry-run flag will stop the listed containers:"
            echo #Spacing
			for i in "${runningContainers[@]}"; do
				local name
				local path
				local args
				name="$(docker inspect -f '{{json .Name}}' "$i")"
				path="$(docker inspect -f '{{json .Path}}' "$i")"
				args="$(docker inspect -f '{{json .Args}}' "$i")"
				echo "Container ID: $i IMAGE: $path/$args NAME: $name"
			done
            echo #Spacing
		fi # End Dry Run
	else
		if [ ! "$runningContainers" ]; then
			echo "No running containers!"
		else
			local count=0
			echo "Stopping running containers..."
			for i in "${runningContainers[@]}"; do
				local output
				local status
				local name
				local path
				local args
				name="$(docker inspect -f '{{json .Name}}' "$i")"
				path="$(docker inspect -f '{{json .Path}}' "$i")"
				args="$(docker inspect -f '{{json .Args}}' "$i")"
				docker stop "$i" &>/dev/null
				status=$?
				if [[ $status -eq 0 ]] ; then
					count=$((count+1))
					output="STOPPED: ID: $i IMAGE: $path/$args NAME: $name"
					echo "$output" | log
				else
					output="COULD NOT STOP: ID: $i IMAGE: $path/$args NAME: $name"
					echo "$output" | log
				fi
			done
			echo "Containers stopped: $count"
		fi
	fi
}


# @info:	Removes all stopped docker containers.
function cleanContainers {
	if $DRY_RUN; then
		echo "Dry run on removal of stopped containers:"
		if [[ ! ${CONTAINERS_TO_DELETE[@]} ]]; then
			echo "No removable containers. Running without -n or --dry-run flag won't remove any containers."
			echo #Spacing
		fi
		if [[ ${CONTAINERS_TO_DELETE[@]} ]]; then
			echo "Running without -n or --dry-run flag will remove the listed containers:"
            echo #Spacing
			for i in "${CONTAINERS_TO_DELETE[@]}"; do
				local name
				local path
				local args
				name="$(docker inspect -f '{{json .Name}}' "$i")"
				path="$(docker inspect -f '{{json .Path}}' "$i")"
				args="$(docker inspect -f '{{json .Args}}' "$i")"
				echo "Container ID: $i IMAGE: $path/$args NAME: $name"
			done
			echo #Spacing
		fi # end dry run
	else
	    if [[ ! "${CONTAINERS_TO_DELETE[@]}" ]]; then
	        echo "No containers To clean!"
	    else
			local count=0
			echo "Cleaning containers..."
			for i in "${CONTAINERS_TO_DELETE[@]}"; do
				local output
				local status
				local name
				local path
				local args
				name="$(docker inspect -f '{{json .Name}}' "$i")"
				path="$(docker inspect -f '{{json .Path}}' "$i")"
				args="$(docker inspect -f '{{json .Args}}' "$i")"
				docker rm "$i" &>/dev/null
				status=$?
				if [[ $status -eq 0 ]] ; then
					count=$((count+1))
					output="DELETED: ID: $i IMAGE: $path/$args NAME: $name"
					echo "$output" | log
				else
					output="COULD NOT DELETE: ID: $i IMAGE: $path/$args NAME: $name"
					echo "$output" | log
				fi
			done
			echo "Stopped containers cleaned: $count"
	    fi
	fi
}

# @info:	Removes all untagged/tagged docker images.
function cleanImages {
	if $DRY_RUN; then
		echo "Dry run on removal of images:"
		if [[ ! ${IMAGES_TO_DELETE[@]} ]]; then
			echo "No images. Running without -n or --dry-run flag won't remove any images."
			echo #Spacing
		else
			echo "Running without -n or --dry-run flag will remove the listed images:"
			echo #Spacing
			local totalSize=0
			for i in "${IMAGES_TO_DELETE[@]}"; do
				local repotag
				local size
				repotag="$(docker inspect -f '{{json .RepoTags}}' "$i")"
				size="$(docker inspect -f '{{json .Size}}' "$i")"
				echo "REPOSITORY/TAG: $repotag IMAGE ID: $i"
				totalSize=$((totalSize+size))
			done
			echoSize $totalSize
			echo #Spacing
		fi # End dry run
	else
		if [[ ! "${IMAGES_TO_DELETE[@]}" ]]; then
	        echo "No images to delete!"
	    else
			local count=0
			local try=0
			echo "Cleaning images..."
			local -a todelete
			todelete="${IMAGES_TO_DELETE[*]}"
			 while [[ "$try" -lt "${#IMAGES_TO_DELETE[@]}" ]]; do
				for i in $(seq 0 "${#IMAGES_TO_DELETE[@]}"); do
					try=$((try+1))
					local output
					local status
					local repotag
					local size
					local image
					local validInput
					validInput=true
					image="${IMAGES_TO_DELETE[$i]}"
					image=${image// /}
					if [[ "${#image}" -lt 12 ]]; then
						validInput=false
					fi
					if [[ $validInput == true ]]; then
						repotag="$(docker inspect -f '{{json .RepoTags}}' "$image")"
						size="$(docker inspect -f '{{json .Size}}' "$image")"
						docker rmi -f "$image" &>/dev/null
						status=$?
						if [[ $status -eq 0 ]] ; then
							count=$((count+1))
							totalSize=$((totalSize+size))
							output="DELETED: REPOSITORY/TAG: $repotag IMAGE ID: $image"
							echo "$output" | log
							#unset "IMAGES_TO_DELETE[$i]" # ERROR value too great for base
							todelete=("${todelete[@]:0:$i}" "${todelete[@]:(($i+1))}")
						fi
					fi
				done
			done
			echo "Images cleaned: $count"
			echoSize $totalSize
	    fi
	fi
}

# @info:	Removes all dangling Docker Volumes.
function cleanVolumes {
	IFS=$'\n' read -rd '' -a danglingVolumes <<<"$(docker volume ls -qf dangling=true)"
	if $DRY_RUN; then
		echo "Dry run on removal of dangling volumes:"
		if [[ ! $danglingVolumes ]]; then
			echo "No existing dangling volumes. Running without -n or --dry-run flag won't remove any dangling volumes."
			echo
		else
			echo "Running without -n or --dry-run flag will stop the listed dangling volumes:"
			for i in "${danglingVolumes[@]}"; do
				local driver
				driver="$(docker volume inspect -f '{{json .Driver}}' "$i")"
				echo "DRIVER: $driver NAME: $i"
				echo # for spacing
			done

		fi
		if [[ ${CONTAINERS_TO_DELETE[@]} ]]; then
			echo "Dangling volumes that would be removed from containers to be deleted..."
			for j in "${CONTAINERS_TO_DELETE[@]}"; do
				local status
				local output
				local driver
				name="$(docker inspect -f '{{json .Mounts}}' "$j")"
				echo VOLUME: "$name"
				echo # for spacing
			done
			echo #For spacing
		fi # End dry run
	else
	    if [ ! "$danglingVolumes" ]; then
	        echo "No dangling volumes!"
	    else
			echo "Cleaning existing dangling volumes..."
			local count=0
			for i in "${danglingVolumes[@]}"; do
				local status
				local output
				local driver
				driver="$(docker volume inspect -f '{{json .Driver}}' "$i")"
				docker volume rm "$i" &>/dev/null
				status=$?
				if [[ $status -eq 0 ]] ; then
					count=$((count+1))
					output="DELETED DRIVER: $driver NAME: $i"
					echo "$output" | log
				else
					output="COULD NOT DELETE DRIVER: $driver NAME: $i"
				fi
			done
			echo "Volumes cleaned: $count"
	    fi
	fi
}

#@ info:	Sets global array of empty networks
function globalEmptyNetworks {
	IFS=$'\n' read -rd '' -a networks <<<"$(docker network ls -q)"
	local -a emptyNetworks
	for i in "${networks[@]}"; do
		containers="$(docker network inspect -f '{{json .Containers}}' "$i")"
		containers=${containers:3} # remove empty container string brackets
		name="$(docker network inspect -f '{{json .Name}}' "$i")"
		if [[ "$name" != '"bridge"' ]] && [[ "$name" != '"host"' ]] && [[ "$name" != '"none"' ]]; then
			emptyNetworks+=("$i")
		fi
	done
	if [[ "${REMAINING_CONTAINERS[@]}" ]]; then
		for j in "${REMAINING_CONTAINERS[@]}";  do
			local -a connectedNetworks
			connectedNetworks="$(docker inspect -f '{{json .NetworkSettings.Networks}}' "$j")"
			length="${#emptyNetworks[@]}"
			for k in $(seq 0 "$length"); do
				checking="${emptyNetworks[$k]}"
				if [[ $connectedNetworks =~ $checking ]]; then
					emptyNetworks=("${emptyNetworks[@]:0:$k}" "${emptyNetworks[@]:(($k+1))}")
				fi
			done
		done
	fi
	for x in "${emptyNetworks[@]}"; do
		echo "$x"
	done
}

function cleanNetworks {
	if [[ $HAS_NETWORK_VERSION == true ]]; then
		if [[ $DRY_RUN == true ]]; then
			echo "Dry run on removal of networks:"
			if [[ ! ${EMPTY_NETWORKS[@]} ]]; then
				echo "No empty networks. Running without -n or --dry-run flag won't remove any networks."
			else
				echo "Running without -n or --dry-run flag will remove the listed networks:"
				for i in "${EMPTY_NETWORKS[@]}"; do
					local name
					name="$(docker network inspect -f '{{json .Name}}' "$i")"
					local driver
					driver="$(docker network inspect -f '{{json .Driver}}' "$i")"
					echo "Network ID: $i NAME: $name DRIVER: $driver"
				done
			fi # End Dry Run
		else
			if [[ "${#EMPTY_NETWORKS[@]}" -eq 0 ]]; then
				echo "No empty networks!"
				echo
			else
				local count=0
				echo "Removing empty networks..."
				for i in "${EMPTY_NETWORKS[@]}"; do
					if docker network rm "$i" 2>&1 | log ; then
						count=$((count+1))
					fi
				done
				echo "Networks removed: $count"
				echo
			fi
		fi
	else
		echo "Docker-clean only has support for Network removal on Docker Versions 1.10 and up."
		echo "Docker will not enable you to remove networks in use, and you can use the "
		echo "following command at your own risk: docker network rm \$(docker network ls -q)"
	fi
}

# @info:	Restarts and reRuns docker-machine env active machine
function restartMachine {
	operating_system=$(testOS)
	#if [[ $DRY_RUN == false ]]; then
		if [[ $operating_system =~ mac || $operating_system =~ windows ]]; then
			active="$(docker-machine active)"
			if [[ $DRY_RUN == false ]]; then
				docker-machine restart "$active"
			else
				echo "Dry run on Daemon restart:"
				echo "Command that would be used: docker-machine restart $active"
			fi
			eval "$(docker-machine env "$active")"
			echo "Running docker-machine env $active..."
			echo "New IP Address for" "$active" ":" "$(docker-machine ip)"
		elif [[ $operating_system =~ linux ]]; then
			if [[ $DRY_RUN == false ]]; then
				echo "Restarting Docker..."
				echo "Restarting this service requires sudo privileges"
			else
				echo "Dry run on Daemon restart, requires sudo to check platform:"
			fi
			init_system=$(linuxInitSystem)
			# Upstart covers SysV and OpenRC as well.
			if [[ $init_system =~ upstart  ]]; then
				if [[ $DRY_RUN == false ]]; then
					sudo service "docker" restart
				else
					echo "Restart command that would be run: sudo service docker restart"
				fi
			elif [[ $init_system =~ systemd ]]; then
				if [[ $DRY_RUN == false ]]; then
					sudo systemctl restart docker.service
				else
					echo "Restart command that would be run: sudo systemctl restart docker.service"
				fi
			elif [[ $init_system =~ rc ]]; then
				if [[ $DRY_RUN == false ]]; then
					sudo launchctl restart "docker"
				else
					echo "Restart command that would be run: sudo launchctl restart docker"
				fi
			fi
		else
			echo It appears your OS is not compatible with our docker engine restart
			echo Windows compatibility work in progress
			echo It you feel you are seeing this as an error please visit
			echo "https://github.com/ZZROTDesign/docker-clean and open an issue."
			exit 2
		fi
}

# @info:	Runs the checks before the main code can be run.
function Check {
	checkDocker
	checkVersion
}

# @info:	Accepts input to output if verbose mode is flagged.
function log {
	read -r IN
	if $VERBOSE; then
		echo "$IN"
	fi
}

## ** Script for testing os **
# Modified for our usage from:
# Credit https://stackoverflow.com/questions/3466166/how-to-check-if-running-in-cygwin-mac-or-linux/17072017#17072017?newreg=b1cdf253d60546f0acfb73e0351ea8be
# Echo mac for Mac OS X, echo linux for GNU/Linux, echo windows for Window
function testOS {
  if [ "$(uname)" == "Darwin" ]; then
      # Do something under Mac OS X platform
      echo mac
  elif [ "$(uname -s)" == "Linux" ]; then
      # Do something under GNU/Linux platform
      echo linux
			#!/bin/bash

  elif [ "$(uname -s)" == "MINGW32_NT" ]; then
      # Do something under Windows NT platform
      echo windows
  fi
}
#END FUNCTIONS

# Function for testing linux initSystem
function linuxInitSystem {
	# To include hidden files
	shopt -s nullglob dotglob

	# Get sudo privileges
	if [ $EUID != 0 ]; then
    sudo "$?" &>/dev/null
	#sudo "$0" "$@" &>/dev/null #Recommended, but doesn't pass shell check
fi
# Directories to check
# Upstart covers SysV and OpenRC as well.
	upstart=(/etc/init.d/docker)
	systemd=(/etc/systemd/docker)
	rc=(/etc/rc.d/docker)
	initSystem=""
	#files=(/some/dir/*)
	if [ ${#upstart[@]} -gt 0 ]; then
		initSystem=upstart
	elif [ ${#systemd[@]} -gt 0 ]; then
		initSystem=systemd
	elif [ ${#rc[@]} -gt 0 ]; then
		initSystem=rc
	fi
	echo $initSystem
}

# @info:	Echos the size of images removed in various measurements
# @args:	The number of bytes moved
function echoSize {
	local mega
	local giga
	if [[ $1 -gt 0 ]]; then
		mega=$(($1 / 1000000))
		giga=$(($1 / 1000000000))
		if [[ $giga == 0 ]]; then
			echo "You've cleared approximately MB: $mega of space!"
		else
			echo "You've cleared approximately MB: $mega or GB: $giga of space!"
		fi
	fi
}

# @info:	Returns 0 if array contains string, 1 if it does not.
# @info:	NOTE: Must run status check after calling to check result.
# @args:	Arg 1 is string, arg2 is array
function arrayContains {
	local seeking=$1; shift
	local in=1
	for element; do
		if [[ "$element" == "$seeking" ]]; then
			in=0
			break
		fi
	done
	echo $in
		#for i in "${@:2}"; do
		#	[[ "$i" == "$1" ]] && return 0;
		#done
		#return 1
}

# @info: sets global container variable arrays
# @args: delete --> returns containers to be deleted, remaining --> returns non-deleted containers
function containersToDelete {
	local -a remainingContainers
	if $STOP_CONTAINERS && $DELETE_CREATED; then
		IFS=$'\n' read -rd '' -a containers <<<"$(docker ps -aq)"
	elif $STOP_CONTAINERS && ! $DELETE_CREATED; then
		IFS=$'\n' read -rd '' -a containers <<<"$(docker ps -q -f STATUS=exited -f STATUS=running)"
		IFS=$'\n' read -rd '' -a remainingContainers <<<"$(docker ps -q -f STATUS=created)"
	elif ! $STOP_CONTAINERS && $DELETE_CREATED; then
		IFS=$'\n' read -rd '' -a containers <<<"$(docker ps -q -f STATUS=exited -f STATUS=created)"
		IFS=$'\n' read -rd '' -a remainingContainers <<<"$(docker ps -q -f STATUS=running)"
	fi

	if [[ $1 =~ delete ]]; then
		for value in "${containers[@]}" ; do
			echo "$value"
		done
	elif [[ $1 =~ remaining ]]; then
		for value in "${remainingContainers[@]}" ; do
			echo "$value"
		done
	fi
}

#@ info sets global images to delete for dry run. CURRENTLY NOT IN USE
function usedImages {
	# For loop goes through appending to array of images with images used in containers queued to remove
	#declare -a used
	for i in "${REMAINING_CONTAINERS[@]}" ; do
		# IF not used by other containers

		new="$(docker inspect -f '{{json .Image}}' "$i")"
		new=${new##*:} 		# Cuts inspect output off before the colon -- "sha:"
		new=${new:0:12} 	# Take only first 12 characters from image sha
		echo "$new"
	done
}

function globalImagesToDelete {
	# starts with all images and then pulls just the unused images
	#if $DELETE_TAGGED; then
	if $DELETE_TAGGED; then
		IFS=$'\n' read -rd '' -a images <<<"$(docker images -a -q)"
	else
		IFS=$'\n' read -rd '' -a images <<<"$(docker images -aq --filter "dangling=true")"
	fi
	#else
	#	IFS=$'\n' read -rd '' -a images <<<"$(docker images -aq --filter "dangling=true")"
	#fi
	for i in "${images[@]}" ; do
		# Call arry contains function
		if [[ $(arrayContains "$i" "${IMAGES_IN_USE[@]}") -eq 1 ]]; then
			echo "$i"
		fi
	done
}


# @info:	sets global variables for a dry run
function setGlobal {
	IFS=$'\n'
	CONTAINERS_TO_DELETE=($(containersToDelete delete))
	REMAINING_CONTAINERS=($(containersToDelete remaining))	# Add time delta
	IMAGES_IN_USE=($(usedImages))
	IMAGES_TO_DELETE=($(globalImagesToDelete))
	EMPTY_NETWORKS=($(globalEmptyNetworks))
	HAS_NETWORK_VERSION=($(checkNetworkVersion))
	#VOLUMES_TO_DELETE=($(volumesToDelete))
}
# @info:	Default run option, cleans stopped containers and images
function dockerClean {
	#if [[ $DRY_RUN == true ]]; then
	setGlobal
	#fi

	if $STOP_CONTAINERS; then
		stop
	fi
	if $CLEAN_CONTAINERS; then
		cleanContainers
	fi
	if $CLEAN_IMAGES; then
		cleanImages
	fi
	if $CLEAN_VOLUMES && $HAS_VERSION; then
		cleanVolumes
	fi
	if $CLEAN_NETWORKS && $HAS_VERSION; then
		cleanNetworks
	fi
	if $RESTART;  then
		restartMachine
	fi
}

# @info:	Main function
Check
parseCli "$@"

# Used for testing global arrays
: <<'END'
echo EMTPY NETWORKS
for i in "${EMPTY_NETWORKS[@]}"; do
	echo "$i"
done
echo USED IMAGES
for i in "${IMAGES_IN_USE[@]}"; do
	echo "$i"
done
echo
echo UNUSED IMAGES
for j in "${IMAGES_TO_DELETE[@]}"; do
	echo "$j"
done
END
exit 0
