#compdef sway-session

_sway_session_contexts() {
	local scope=$1 prefix=$2 output line uuid description
	local -a values descriptions

	output=$(command sway-session completion contexts "$scope" 2>/dev/null) || return 0
	while IFS= read -r line || [[ -n $line ]]; do
		[[ $line == *$'\t'* && $line != *$'\t'*$'\t'* ]] || continue
		uuid=${line%%$'\t'*}
		description=${line#*$'\t'}
		[[ -n $description ]] || continue
		[[ $uuid =~ '^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$' ]] || continue
		[[ $uuid != 00000000-0000-0000-0000-000000000000 ]] || continue
		[[ $uuid == ${prefix}* ]] || continue
		values+=("$uuid")
		descriptions+=("$description")
	done <<< "$output"
	(( ${#values} )) && compadd -d descriptions -- "${values[@]}"
}

_sway_session_context_pending() {
	local skip_next=0 word
	shift
	for word in "$@"; do
		if (( skip_next )); then
			skip_next=0
			continue
		fi
		case $word in
			--socket|--desktop-id|--label) skip_next=1 ;;
			--json|-h|--help|--yes|--require-active|--preview) ;;
			--*) ;;
			*) return 1 ;;
		esac
	done
	return 0
}

_sway_session_restore_scope() {
	local skip_next=0 word scope=restore
	for word in "$@"; do
		if (( skip_next )); then
			skip_next=0
			continue
		fi
		case $word in
			--socket) skip_next=1 ;;
			--preview) return 0 ;;
			--) break ;;
			--require-active) scope=restore-active ;;
		esac
	done
	print -r -- "$scope"
}

_sway_session_add() {
	local value
	local -a candidates
	for value in "$@"; do
		if (( ${global_options_ended:-0} )) && [[ $value == --json || $value == -h || $value == --help ]]; then
			continue
		fi
		candidates+=("$value")
	done
	(( ${#candidates} )) && compadd -- "${candidates[@]}"
	return 0
}

_sway_session_marker_is_value() {
	local command=${arguments[1]-} app_command=${arguments[2]-} start=1 word pending=0 parsing=1
	local value_options=''
	case $command in
		terminal) value_options=' --project --context --cwd --label --socket --role --remote --remote-session --machine ' ;;
		register) value_options=' --session --cwd --label --provider --id ' ;;
		restore|status|daemon|broker) value_options=' --socket ' ;;
		restore-report) value_options=' --socket --retry ' ;;
		state) start=2; value_options=' --output --from --retry --cancel --after --socket ' ;;
		doctor) value_options=' --fix --shortcuts --socket --sway-config ' ;;
		request-start) value_options=' --session --cwd --label --provider --workspace ' ;;
		app)
			start=2
			case $app_command in
				register-focused|rebind-focused) value_options=' --socket --desktop-id ' ;;
				register-workspace|list|forget) value_options=' --socket ' ;;
				status) value_options=' --socket --context ' ;;
			esac
			;;
	esac
	for word in "${arguments[@]:${start}}"; do
		if (( pending )); then
			pending=0
			continue
		fi
		(( parsing )) || return 1
		case $word in
			--)
				parsing=0
				;;
			--*=*)
				;;
			--*)
				[[ $value_options == *" $word "* ]] && pending=1
				;;
			*)
				parsing=0
				;;
		esac
	done
	(( pending ))
}

_sway_session_app_inventory_arguments_valid() {
	local pending='' word
	app_inventory=0 app_inventory_value=''
	for word in "${arguments[@]:2}"; do
		if [[ -n $pending ]]; then
			pending=''
			continue
		fi
		case $word in
			--socket|--context) pending=$word ;;
			--inventory|--inventory=true|--inventory=1) app_inventory=1 ;;
			--inventory=false|--inventory=0) app_inventory=0 ;;
			--socket=*|--context=*|--json|-h|--help) ;;
			*) return 1 ;;
		esac
	done
	app_inventory_value=$pending
	return 0
}

_sway_session_doctor_arguments_valid() {
	local pending='' word
	doctor_has_fix=0 doctor_has_check=0 doctor_fix_id=''
	for word in "${arguments[@]:1}"; do
		if [[ -n $pending ]]; then
			[[ $pending == fix ]] && doctor_fix_id=$word
			pending=''
			continue
		fi
		case $word in
			--fix) doctor_has_fix=1; pending=fix ;;
			--fix=*) doctor_has_fix=1; doctor_fix_id=${word#--fix=} ;;
			--shortcuts|--socket|--sway-config) pending=value ;;
			--check|--check=true|--check=1) doctor_has_check=1 ;;
			--check=false|--check=0) doctor_has_check=0 ;;
			--yes|--adopt-standard|--json|-h|--help|--*=*) ;;
			--*) ;;
			*) return 1 ;;
		esac
	done
	return 0
}

_sway-session() {
	local cur=${words[CURRENT]} word command='' app_command='' context_scope='' index options_ended=0 terminator_arguments=0 global_options_ended=0 invalid_command_option=0 global_value_pending=0
	local -a arguments

	for (( index = 2; index < CURRENT; index++ )); do
		word=${words[index]}
		if (( global_value_pending )); then
			global_value_pending=0
			continue
		fi
		if (( options_ended )); then
			arguments+=("$word")
			(( terminator_arguments += 1 ))
			continue
		fi
		case $word in
			--config) global_value_pending=1; continue ;;
			--config=*) continue ;;
			--json|-h|--help)
				if (( global_options_ended )); then
					_sway_session_marker_is_value || invalid_command_option=1
					arguments+=("$word")
				fi
				continue
				;;
			--)
				global_options_ended=1
				if _sway_session_marker_is_value; then
					arguments+=("$word")
				else
					options_ended=1
				fi
				continue
				;;
		esac
		arguments+=("$word")
	done

	command=${arguments[1]-}
	if [[ ${words[CURRENT-1]-} == --config ]]; then
		_files
		return
	fi
	if [[ $command == --config ]]; then
		_files
		return
	fi
	(( invalid_command_option )) && return 0
	if [[ -z $command ]]; then
		(( options_ended )) && return 0
		_sway_session_add terminal register restore restore-report list status archive activate purge app daemon broker request-start report-agent-session completion doctor state version --config --json --version -h --help
		return
	fi
	app_command=${arguments[2]-}
	if (( options_ended )); then
		(( terminator_arguments == 0 )) || return 0
		case $command in
			restore)
				if _sway_session_context_pending restore "${arguments[@]:1}"; then
					context_scope=$(_sway_session_restore_scope "${arguments[@]:1}")
					[[ -n $context_scope ]] && _sway_session_contexts "$context_scope" "$cur"
				fi
				;;
			purge)
				_sway_session_context_pending "$command" "${arguments[@]:1}" && _sway_session_contexts "$command" "$cur"
				;;
			app)
				if [[ $app_command == forget ]] && _sway_session_context_pending app-forget "${arguments[@]:2}"; then
					_sway_session_contexts app-forget "$cur"
				fi
				;;
		esac
		return 0
	fi

	case $command in
		state)
			case $app_command in
				'') _sway_session_add backup recover operations --json -h --help ;;
				backup)
					[[ ${arguments[-1]-} == --output ]] && { _files; return; }
					_sway_session_add --output --json -h --help
					;;
				operations)
					case ${arguments[-1]-} in --retry|--cancel|--after) return ;; --socket) _files; return ;; esac
					_sway_session_add --retry --cancel --after --socket --json -h --help
					;;
				recover)
					[[ ${arguments[-1]-} == --from ]] && { _files; return; }
					_sway_session_add --from --yes --json -h --help
					;;
			esac
			;;
		version|--version)
			_sway_session_add --json -h --help
			;;
		terminal)
			case ${arguments[-1]-} in
				--cwd) _files; return ;;
				--context) _sway_session_contexts terminal-status "$cur"; return ;;
				--role) _sway_session_add shell agy amp claude cline codex copilot cursor devin droid gemini grok hermes kilo kimi kiro maki mastracode omp opencode pi qodercli qwen; return ;;
				--project|--label|--socket|--remote|--remote-session|--machine) return ;;
			esac
			if [[ ${arguments[2]-} == list ]]; then
				_sway_session_add --json -h --help
			elif [[ ${arguments[2]-} == manage ]]; then
				[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
				_sway_session_add --socket -h --help
			elif [[ ${arguments[2]-} == status ]]; then
				_sway_session_add --project --json -h --help
				if [[ $cur != -* ]] && _sway_session_context_pending terminal-status "${arguments[@]:2}"; then
					_sway_session_contexts terminal-status "$cur"
				fi
			elif [[ ${arguments[2]-} == cleanup ]]; then
				[[ ${arguments[-1]-} == --archived-before ]] && return
				_sway_session_add --archived-before --json -h --help
			elif [[ ${arguments[2]-} == reconfigure ]]; then
				[[ ${arguments[-1]-} == --project || ${arguments[-1]-} == --socket ]] && return
				_sway_session_add --project --socket --json -h --help
			elif [[ ${arguments[2]-} == forget ]]; then
                _sway_session_add --yes --socket --json -h --help
		elif [[ ${arguments[2]-} == rename ]]; then
				[[ ${arguments[-1]-} == --label ]] && return
				_sway_session_add --label --json -h --help
				if [[ $cur != -* ]] && _sway_session_context_pending terminal-status "${arguments[@]:2}"; then
					_sway_session_contexts terminal-status "$cur"
				fi
			else
				_sway_session_add manage list status cleanup rename reconfigure forget --new --context --project --cwd --label --socket --role --remote --remote-session --machine --ephemeral --json -h --help
			fi
			;;
		register)
			if [[ ${arguments[-1]-} == --cwd ]]; then
				_files
			elif [[ ${arguments[-1]-} == --session || ${arguments[-1]-} == --label || ${arguments[-1]-} == --provider || ${arguments[-1]-} == --id ]]; then
				return
			else
				_sway_session_add --session --cwd --label --provider --id --json -h --help
			fi
			;;
		restore)
			if [[ ${arguments[-1]-} == --socket ]]; then
				_files
			elif _sway_session_context_pending restore "${arguments[@]:1}"; then
				_sway_session_add --socket --require-active --preview --json -h --help
				if [[ $cur != -* ]]; then
					context_scope=$(_sway_session_restore_scope "${arguments[@]:1}")
					[[ -n $context_scope ]] && _sway_session_contexts "$context_scope" "$cur"
				fi
			else
				_sway_session_add --json -h --help
			fi
			;;
		restore-report)
			case ${arguments[-1]-} in
				--socket) _files; return ;;
				--retry) _sway_session_contexts restore-active "$cur"; return ;;
			esac
			_sway_session_add --retry --socket --json -h --help
			;;
		doctor)
			local doctor_has_fix=0 doctor_has_check=0 doctor_fix_id=''
			_sway_session_doctor_arguments_valid || return 0
			case ${arguments[-1]-} in
				--socket|--sway-config) _files; return ;;
				--fix) _sway_session_add sway.integration; return ;;
				--shortcuts)
					[[ $doctor_fix_id == sway.integration ]] && (( !doctor_has_check )) && _sway_session_add none default
					return 0
					;;
			esac
			if [[ $cur == --shortcuts=* ]]; then
				[[ $doctor_fix_id == sway.integration ]] && (( !doctor_has_check )) && _sway_session_add --shortcuts=none --shortcuts=default
				return 0
			fi
			if (( doctor_has_fix )); then
				if [[ $doctor_fix_id == sway.integration ]] && (( !doctor_has_check )); then
					_sway_session_add --fix --yes --adopt-standard --shortcuts --socket --sway-config --json -h --help
				else
					_sway_session_add --fix --yes --socket --sway-config --json -h --help
				fi
			elif (( doctor_has_check )); then
				_sway_session_add --check --socket --sway-config --json -h --help
			else
				_sway_session_add --check --fix --socket --sway-config --json -h --help
			fi
			;;
		report-agent-session)
			_sway_session_add --codex-hook --json -h --help
			;;
		list)
			_sway_session_add --json -h --help
			;;
		archive|activate|purge)
			if _sway_session_context_pending "$command" "${arguments[@]:1}"; then
				if [[ $command == purge ]]; then
					_sway_session_add --yes --json -h --help
				else
					_sway_session_add --json -h --help
				fi
				[[ $cur == -* ]] || _sway_session_contexts "$command" "$cur"
			else
				_sway_session_add --json -h --help
			fi
			;;
		status|daemon|broker)
			if [[ ${arguments[-1]-} == --socket ]]; then
				_files
			else
				_sway_session_add --socket --json -h --help
			fi
			;;
		request-start)
			if [[ ${arguments[-1]-} == --cwd ]]; then
				_files
			elif [[ ${arguments[-1]-} == --session || ${arguments[-1]-} == --label || ${arguments[-1]-} == --provider || ${arguments[-1]-} == --workspace ]]; then
				return
			else
				_sway_session_add --session --cwd --label --provider --workspace --json -h --help
			fi
			;;
		completion)
			case ${arguments[2]-} in
				'') _sway_session_add contexts --json -h --help ;;
				contexts)
					if [[ -z ${arguments[3]-} ]]; then
						_sway_session_add archive activate restore restore-active purge terminal-status app-forget app-status
					elif [[ $cur == -* ]]; then
						_sway_session_add --json -h --help
					fi
					;;
			esac
			;;
		app)
			if [[ -z $app_command ]]; then
				_sway_session_add register-focused register-workspace confirm status list rebind-focused reapprove pin unpin archive activate forget --json -h --help
				return
			fi
			case $app_command in
				register-focused)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					[[ ${arguments[-1]-} == --desktop-id ]] && return
					_sway_session_add --socket --desktop-id --yes --json -h --help
					;;
				register-workspace)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					_sway_session_add --socket --yes --json -h --help
					;;
				confirm|pin|unpin|archive|activate)
					_sway_session_add --json -h --help
					;;
				status|list)
					local app_inventory=0 app_inventory_value=''
					_sway_session_app_inventory_arguments_valid || return 0
					case $app_inventory_value in
						--socket) _files; return ;;
						--context) [[ $app_command == status ]] && _sway_session_contexts app-status "$cur"; return 0 ;;
					esac
					if [[ $app_command == status ]]; then
						if [[ $cur == --context=* ]]; then
							compset -P '*=' 2>/dev/null || true
							_sway_session_contexts app-status "${cur#--context=}"
							return 0
						fi
						_sway_session_add --context --inventory --socket --json -h --help
					elif (( app_inventory )); then
						_sway_session_add --inventory --socket --json -h --help
					else
						_sway_session_add --inventory --json -h --help
					fi
					;;
				rebind-focused)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					[[ ${arguments[-1]-} == --desktop-id ]] && return
					if _sway_session_context_pending app-rebind "${arguments[@]:2}"; then
						_sway_session_add --socket --desktop-id --yes --json -h --help
					else
						_sway_session_add --json -h --help
					fi
					;;
				reapprove)
					if _sway_session_context_pending app-reapprove "${arguments[@]:2}"; then
						_sway_session_add --yes --json -h --help
					else
						_sway_session_add --json -h --help
					fi
					;;
				forget)
					[[ ${arguments[-1]-} == --socket ]] && { _files; return; }
					if _sway_session_context_pending app-forget "${arguments[@]:2}"; then
						_sway_session_add --socket --yes --json -h --help
						[[ $cur == -* ]] || _sway_session_contexts app-forget "$cur"
					else
						_sway_session_add --json -h --help
					fi
					;;
			esac
			;;
	esac
	return 0
}
