#!/usr/bin/env bash

basedir="$(cd "$(dirname "$0")/.." && pwd)"
# shellcheck source=../lib/tmux.bash
. "$basedir/lib/tmux.bash"

find_projects() {
	local -a base_dirs rooters rooter_opts

	IFS=',' read -ra base_dirs < <(get_tmux_option '@project-base-dirs')
	IFS=',' read -ra rooters < <(get_tmux_option '@project-rooters' '.git')

	for rooter in "${rooters[@]}"; do
		rooter_opts+=("-o" "-name" "$rooter")
	done
	rooter_opts=('(' "${rooter_opts[@]:1}" ')')

	for base_dir in "${base_dirs[@]}"; do
		# If the base_dir is empty, skip it
		if [[ -z "$base_dir" ]]; then
			continue
		fi

		local -a tmp
		IFS=':' read -ra tmp <<<"$base_dir"
		path="${tmp[0]}"
		min_depth="${tmp[1]:-0}"
		max_depth="${tmp[2]:-${min_depth}}"

		if [[ min_depth -eq 0 && max_depth -eq 0 ]]; then
			# If min_depth and max_depth are both 0, that means we
			# want to add the base_dir itself as a project.
			# In that case, add the base_dir as a project even if it
			# contains no rooter.
			if [[ -d "$path" || -L "$path" ]]; then
				echo "$path"
			fi
		else
			find "$path" -mindepth "$((min_depth + 1))" \
				-maxdepth "$((max_depth + 1))" \
				"${rooter_opts[@]}" \
				-printf '%h\n'
		fi
	done
}

# Convert a path to a session name. The session name is the last component of
# the path. Dots are replaced with underscores. If the path starts with a dot,
# the dot is removed.
# e.g. /home/username/.emacs.d -> emacs_d
to_session_name() {
	local session_name="$1"

	session_name="${session_name##*/}"

	# Dots are not allowed in a tmux session name
	# e.g. .emacs.d -> _emacs_d
	session_name="${session_name//./_}"
	# If the path starts with a slash (a dot), remove it
	# e.g. .emacs.d -> _emacs_d -> emacs_d
	session_name="${session_name#_}"

	echo "$session_name"
}

main() {
	local fzf_opts fzf_tmux_layout_opts selected_path session_name

	# shellcheck disable=SC2207
	fzf_opts="$(get_tmux_option "@project-fzf-opts" "--preview 'ls {}'")"
	# shellcheck disable=SC2207
	fzf_tmux_layout_opts="$(get_tmux_option "@project-fzf-tmux-layout-opts")"

	selected_path="$(find_projects | eval "fzf-tmux ${fzf_tmux_layout_opts} -- ${fzf_opts}")"
	if [[ -z "$selected_path" ]]; then
		return 0
	fi

	# If the selected project has .tmuxinator.yml file, use tmuxinator to
	# start the session.
	if command -v tmuxinator &>/dev/null && [[ -f "${selected_path}/.tmuxinator.yml" ]]; then
		tmuxinator start -p "${selected_path}/.tmuxinator.yml"
		return 0
	fi

	session_name="$(to_session_name "$selected_path")"

	# If the session already exists, attach to it. Otherwise, create a new
	# session and attach to it.
	if ! tmux has-session -t "$session_name" 2>/dev/null; then
		# Return 0 even if creating the session fails.
		tmux new-session -d -s "$session_name" -c "$selected_path" \; \
			set -t "$session_name" destroy-unattached off || :
	fi
	tmux switch-client -t "$session_name"
}

main "$@"
