# Naming convention:
# * _camelCase for function names
# * snake_case for variable names

# all functions will return 0 if they successfully complete the argument
# (or establish there is no need or no way to complete), and something
# other than 0 if that's not the case

# complete arguments to global options
_completeGlobalOptArgs() {
    # arguments to options that take paths as arguments: complete paths
    for el in ${path_arg_global_opts}; do
        if [[ ${prev} == ${el} ]]; then
            COMPREPLY=( $(compgen -f -- ${cur}) )
            return 0
        fi
    done

    # arguments to options that take generic arguments: don't complete
    for el in ${generic_arg_global_opts}; do
        if [[ ${prev} == ${el} ]]; then
            return 0
        fi
    done
    return 1
}

# complete root subcommands and options
_completeRoot() {
    # if we're completing an option
    if [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${global_opts}" -- ${cur}) )
        return 0
    fi
    # complete root commands
    COMPREPLY=( $(compgen -W "${root_commands}" -- ${cur}) )
    return 0
}

# complete names of Compose services
_completeServiceNames() {
    # ideally we should complete service names,
    # but parsing the compose spec file in the
    # completion script is quite complex
    return 0
}

# complete commands to run inside containers
_completeCommand() {
    # we would need to complete commands to run inside
    # a container
    return 0
}


# complete the arguments for `podman-compose up` and return 0
_completeUpArgs() {
    up_opts="${help_opts} -d --detach --no-color --quiet-pull --no-deps --force-recreate --always-recreate-deps --no-recreate --no-build --no-start --build --abort-on-container-exit -t --timeout -V --renew-anon-volumes --remove-orphans --scale --exit-code-from --pull --pull-always --build-arg --no-cache"
    if [[ ${prev} == "--scale" || ${prev} == "-t" || ${prev} == "--timeout" ]]; then
        return 0
    elif [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${up_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi

}

# complete the arguments for `podman-compose exec` and return 0
_completeExecArgs() {
    exec_opts="${help_opts} -d --detach --privileged -u --user -T --index -e --env -w --workdir"
    if [[ ${prev} == "-u" || ${prev} == "--user" || ${prev} == "--index" || ${prev} == "-e" || ${prev} == "--env" || ${prev} == "-w" || ${prev} == "--workdir" ]]; then
        return 0
    elif [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${exec_opts}" -- ${cur}) )
        return 0
    elif [[ ${comp_cword_adj} -eq 2 ]]; then
        # complete service name
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
    elif [[ ${comp_cword_adj} -eq 3 ]]; then
        _completeCommand
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi

}


# complete the arguments for `podman-compose down` and return 0
_completeDownArgs() {
    down_opts="${help_opts} -v --volumes -t --timeout --remove-orphans"
    if [[ ${prev} == "-t" || ${prev} == "--timeout" ]]; then
        return 0
    elif [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${down_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi

}


# complete the arguments for `podman-compose build` and return 0
_completeBuildArgs() {
    build_opts="${help_opts} --pull --pull-always --build-arg --no-cache"
    if [[ ${prev} == "--build-arg" ]]; then
        return 0
    elif [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${build_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi
}

# complete the arguments for `podman-compose logs` and return 0
_completeLogsArgs() {
    logs_opts="${help_opts} -f --follow -l --latest -n --names --since -t --timestamps --tail --until"
    if [[ ${prev} == "--since" || ${prev} == "--tail" || ${prev} == "--until" ]]; then
        return 0
    elif [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${logs_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi
}

# complete the arguments for `podman-compose ps` and return 0
_completePsArgs() {
    ps_opts="${help_opts} -q --quiet"
    if [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${ps_opts}" -- ${cur}) )
        return 0
    else
        return 0
    fi
}

# complete the arguments for `podman-compose pull` and return 0
_completePullArgs() {
    pull_opts="${help_opts} --force-local"
    if [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${pull_opts}" -- ${cur}) )
        return 0
    else
        return 0
    fi
}

# complete the arguments for `podman-compose push` and return 0
_completePushArgs() {
    push_opts="${help_opts} --ignore-push-failures"
    if [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${push_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi
}

# complete the arguments for `podman-compose restart` and return 0
_completeRestartArgs() {
    restart_opts="${help_opts} -t --timeout"
    if [[ ${prev} == "-t" || ${prev} == "--timeout" ]]; then
        return 0
    elif [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${restart_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi
}

# complete the arguments for `podman-compose stop` and return 0
_completeStopArgs() {
    stop_opts="${help_opts} -t --timeout"
    if [[ ${prev} == "-t" || ${prev} == "--timeout" ]]; then
        return 0
    elif [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${stop_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi
}

# complete the arguments for `podman-compose start` and return 0
_completeStartArgs() {
    start_opts="${help_opts}"
    if [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${start_opts}" -- ${cur}) )
        return 0
    else
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
        return 0
    fi
}

# complete the arguments for `podman-compose run` and return 0
_completeRunArgs() {
    run_opts="${help_opts} -d --detach --privileged -u --user -T --index -e --env -w --workdir"
    if [[ ${prev} == "-u" || ${prev} == "--user" || ${prev} == "--index" || ${prev} == "-e" || ${prev} == "--env" || ${prev} == "-w" || ${prev} == "--workdir" ]]; then
        return 0
    elif  [[ ${cur} == -* ]]; then
        COMPREPLY=( $(compgen -W "${run_opts}" -- ${cur}) )
        return 0
    elif [[ ${comp_cword_adj} -eq 2 ]]; then
        # complete service name
        _completeServiceNames
        if [[ $? -eq 0 ]]; then
            return 0
        fi
    elif [[ ${comp_cword_adj} -eq 3 ]]; then
        _completeCommand
        if [[ $? -eq 0 ]]; then
            return 0
        fi
    fi
}


_podmanCompose() {
    cur="${COMP_WORDS[COMP_CWORD]}"
	prev="${COMP_WORDS[COMP_CWORD-1]}"
    root_commands="help version pull push build up down ps run exec start stop restart logs"

    # options to output help text (used as global and subcommand options)
    help_opts="-h --help"

    # global options that don't take additional arguments
    basic_global_opts="${help_opts} -v --no-ansi --no-cleanup --dry-run" 

    # global options that take paths as arguments
    path_arg_global_opts="-f --file --podman-path"
    path_arg_global_opts_array=($arg_global_opts)

    # global options that take arguments that are not files
    generic_arg_global_opts="-p --project-name --podman-path --podman-args --podman-pull-args --podman-push-args --podman-build-args --podman-inspect-args --podman-run-args --podman-start-args --podman-stop-args --podman-rm-args --podman-volume-args"
    generic_arg_global_opts_array=($generic_arg_global_opts)

    # all global options that take arguments
    arg_global_opts="${path_arg_global_opts} ${generic_arg_global_opts}"
    arg_global_opts_array=($arg_global_opts)

    # all global options
    global_opts="${basic_global_opts} ${arg_global_opts}"

    chosen_root_command=""


    _completeGlobalOptArgs
    if [[ $? -eq 0 ]]; then
        return 0
    fi
   
    # computing comp_cword_adj, which thruthfully tells us how deep in the subcommands tree we are
    # additionally, set the chosen_root_command if possible
    comp_cword_adj=${COMP_CWORD}
    if [[ ${COMP_CWORD} -ge 2 ]]; then
        skip_next="no"
        for el in ${COMP_WORDS[@]}; do
            # if the user has asked for help text there's no need to complete further
            if [[ ${el} == "-h" || ${el} == "--help" ]]; then
                return 0
            fi
            if [[ ${skip_next} == "yes" ]]; then
                let "comp_cword_adj--"
                skip_next="no"
                continue
            fi
            if [[ ${el} == -* && ${el} != ${cur} ]]; then
                let "comp_cword_adj--"
                
                for opt in ${arg_global_opts_array[@]}; do
                    if [[ ${el} == ${opt} ]]; then
                        skip_next="yes"
                    fi
                done
            elif [[ ${el} != ${cur} && ${el} != ${COMP_WORDS[0]} && ${chosen_root_command} == "" ]]; then
                chosen_root_command=${el}
            fi
        done
    fi
    
    if [[ ${comp_cword_adj} -eq 1 ]]; then
       _completeRoot

       # Given that we check the value of comp_cword_adj outside
       # of it, at the moment _completeRoot should always return
       # 0, this is just here in case changes are made. The same
       # will apply to similar functions below
        if [[ $? -eq 0 ]]; then
            return 0
        fi
    fi
    case $chosen_root_command in
        up)
            _completeUpArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        down)
            _completeDownArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        exec)
            _completeExecArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        build)
            _completeBuildArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        logs)
            _completeLogsArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        ps)
            _completePsArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        pull)
            _completePullArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        push)
            _completePushArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        restart)
            _completeRestartArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        start)
            _completeStartArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        stop)
            _completeStopArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
        run)
            _completeRunArgs
            if [[ $? -eq 0 ]]; then
                return 0
            fi
            ;;
    esac
}

complete -F _podmanCompose podman-compose
