#compdef yunohost
#
# -----------------------------------------------------------------------------
# Description
# -----------
#  Completion script for yunohost, automatically generated from the action map
#  decribed by `yunohost.yml`
# -----------------------------------------------------------------------------

local state line curcontext

# For debug purposes only
__log() {
    echo $@ >> '/tmp/zsh-completion.log'
}

# First argument: The name of the completion list
# 2nd argument:   The command to get it
# (( $+functions[__get_ynh_cache] )) ||
function __get_ynh_cache() {
    # Checking a global cache policy is defined,
    # and linkage to ynh-cache-policy
    local update_policy completion_items
    zstyle -s ":completion:${curcontext}:" cache-policy update_policy
    if [[ -z "$update_policy" ]]; then
        zstyle ":completion:${curcontext}:" cache-policy __yunohost_cache_policy
    fi
    # If the cache is invalid (too old), regenerate it
    if _cache_invalid $1 || ! _retrieve_cache $1; then
        completion_items=(`eval $2`)
        _store_cache $1 completion_items
    else
        _retrieve_cache $1
    fi
    echo $completion_items
}

# (( $+functions[__yunohost_cache_policy] )) ||
__yunohost_cache_policy(){
    local cache_file="$1"
    # Rebuild if the yunohost executable is newer than cache
    [[ "${commands[yunohost]}" -nt "${cache_file}" ]] && return

    # Rebuild if cache is more than a week old
    local -a oldp
    # oldp=( "$1"(mM+1) ) # month
    # oldp=( "$1"(Nm+7) ) # 1 week
    oldp=( "$1"(Nmd+1) ) # 1 day
    (( $#oldp )) && return
    return 1
}

#
# Routing function, used to go through $words and find the correct subfunction
# (Suggestions welcome to improve that design... =/ )
# (( $+functions[__jump] )) ||
function __jump() {
    local cmd

    # Remember the subcommand name
    if (( ${#@} == 0 )); then
        local cmd=${words[2]}
    else
        cmd=$1 # < no more used?
    fi

    # Set the context for the subcommand
    ynhcommand="${ynhcommand}_${cmd}"
    # Narrow the range of words we are looking at to exclude `yunohost`
    (( CURRENT-- ))
    shift words
    # Run the completion for the subcommand
    if ! _call_function ret ${ynhcommand#:*:}; then
        _default && ret=0
    fi
    return ret
}

#-----------------------------------------
#   Command
#-----------------------------------------
#
# Principal entry point with general options and list of commands
# (( $+functions[_yunohost] )) ||
function _yunohost() {
    local curcontext="${curcontext}" state line ret=1
    local mode
    # `ynhcommand` is where `__jump` builds the name of the completion function
    ynhcommand='_yunohost'

    typeset -ag common_options; common_options=(
        '(-h --help)'{-h,--help}'[Show this help message and exit]:help:'
        '--version[Display YunoHost packages versions]:version:'
        '--output-as[Output result in another format]:output-as:(json plain none)'
        '--debug[Log and print debug messages]'
        '--quiet[Don'"'"'t produce any output]'
        '--timeout[Number of seconds before this command will timeout because it can'"'"'t acquire the lock (meaning that another command is currently running), by default there is no timeout and the command will wait until it can get the lock]:timeout:'
    )

    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_categories; yunohost_categories=(
            'user:Manage users and groups'
            'domain:Manage domains'
            'app:Manage apps'
            'backup:Manage backups'
            'settings:Manage YunoHost global settings'
            'service:Manage services'
            'firewall:Manage firewall rules'
            'dyndns:Subscribe and Update DynDNS Hosts ( deprecated, use '"'"'yunohost domain dyndns'"'"' instead )'
            'tools:Specific tools'
            'hook:Manage hooks'
            'log:Manage debug logs'
            'diagnosis:Look for possible issues on the server'
            'storage:Manage hard-drives, filesystem, pools'
        )
        _describe -V -t yunohost-commands 'yunohost category' yunohost_categories "$@"
    fi

    _arguments -s -C $common_options
    # unset common_option
}

#-----------------------------------------
#   Subcommands
#-----------------------------------------
#-----------------------------------------
#               user
#-----------------------------------------

# (( $+functions[_yunohost_user] )) ||
function _yunohost_user() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_user; yunohost_user=(
            'list:List users'
            'create:Create user'
            'delete:Delete user'
            'update:Update user informations'
            'info:Get user information'
            'export:Export users into CSV'
            'import:Import several users from CSV'
        )
        _describe -V -t yunohost-user 'yunohost user category' yunohost_user "$@"
        
        local -a yunohost_user_subcategories; yunohost_user_subcategories=(
            'group:Manage user groups'
            'permission:Manage permissions'
            'ssh:Manage ssh access'
        )
        _describe -V -t yunohost-user-subcategories 'yunohost user subcategories' yunohost_user_subcategories "$@"
    fi
}



# (( $+functions[_yunohost_user_list] )) ||
function _yunohost_user_list() {
    _arguments -s -C \
        '(*)--fields[fields to fetch (username, fullname, mail, mail-alias, mail-forward, mailbox-quota, groups, shell, home-path)]:*:fields:(username fullname mail mail-alias mail-forward mailbox-quota groups shell home-path)' 
}

# (( $+functions[_yunohost_user_create] )) ||
function _yunohost_user_create() {
    _arguments -s -C \
        '1:The unique username to create:' \
        '(-F --fullname)'{-F,--fullname}'[The full name of the user. For example '"'"'Camille Dupont'"'"']:fullname:' \
        '(-p --password)'{-p,--password}'[User password]:password:' \
        '(-d --domain)'{-d,--domain}'[Domain for the email address]:domain:__ynh_domain_list' \
        '(-q --mailbox-quota)'{-q,--mailbox-quota}'[Mailbox size quota]:mailbox-quota:' \
        '(-s --loginShell)'{-s,--loginShell}'[The login shell used]:loginShell:' 
}

# (( $+functions[_yunohost_user_delete] )) ||
function _yunohost_user_delete() {
    _arguments -s -C \
        '1:Username to delete:__ynh_user_list_fields_username' \
        '--purge[Purge user'"'"'s home and mail directories]' \
        '--force[Force user deletion]' 
}

# (( $+functions[_yunohost_user_update] )) ||
function _yunohost_user_update() {
    _arguments -s -C \
        '1:Username to update:__ynh_user_list_fields_username' \
        '(-F --fullname)'{-F,--fullname}'[The full name of the user. For example '"'"'Camille Dupont'"'"']:fullname:' \
        '(-m --mail)'{-m,--mail}'[mail]:mail:' \
        '(-p --change-password)'{-p,--change-password}'[New password to set]:change-password:' \
        '(*)--add-mailforward[Mailforward addresses to add]:*:add-mailforward:' \
        '(*)--remove-mailforward[Mailforward addresses to remove]:*:remove-mailforward:' \
        '(*)--add-mailalias[Mail aliases to add]:*:add-mailalias:' \
        '(*)--remove-mailalias[Mail aliases to remove]:*:remove-mailalias:' \
        '(-q --mailbox-quota)'{-q,--mailbox-quota}'[Mailbox size quota]:mailbox-quota:' \
        '(-s --loginShell)'{-s,--loginShell}'[The login shell used]:loginShell:' 
}

# (( $+functions[_yunohost_user_info] )) ||
function _yunohost_user_info() {
    _arguments -s -C \
        '1:Username or email to get information:__ynh_user_list_fields_username' 
}

# (( $+functions[_yunohost_user_export] )) ||
function _yunohost_user_export() { }

# (( $+functions[_yunohost_user_import] )) ||
function _yunohost_user_import() {
    _arguments -s -C \
        '1:CSV file with columns username, firstname, lastname, password, mail, mailbox-quota, mail-alias, mail-forward, groups (separated by coma):_files' \
        '(-u --update)'{-u,--update}'[Update all existing users contained in the CSV file (by default existing users are ignored)]' \
        '(-d --delete)'{-d,--delete}'[Delete all existing users that are not contained in the CSV file (by default existing users are kept)]' 
}


#-----------------------------------------
#               user_group
#-----------------------------------------

# (( $+functions[_yunohost_user_group] )) ||
function _yunohost_user_group() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_user_group; yunohost_user_group=(
            'list:List existing groups'
            'create:Create group'
            'delete:Delete group'
            'info:Get information about a specific group'
            'add:Add users to group'
            'remove:Remove users from group'
            'add-mailalias:Add mail aliases to group'
            'remove-mailalias:Remove mail aliases to group'
        )
        _describe -V -t yunohost-user_group 'yunohost user_group category' yunohost_user_group "$@"
        
    fi
}



# (( $+functions[_yunohost_user_group_list] )) ||
function _yunohost_user_group_list() {
    _arguments -s -C \
        '(-f --full)'{-f,--full}'[Display all informations known about each groups]' \
        '(-p --include-primary-groups)'{-p,--include-primary-groups}'[Also display primary groups (each user has an eponym group that only contains itself)]' 
}

# (( $+functions[_yunohost_user_group_create] )) ||
function _yunohost_user_group_create() {
    _arguments -s -C \
        '1:Name of the group to be created:' 
}

# (( $+functions[_yunohost_user_group_delete] )) ||
function _yunohost_user_group_delete() {
    _arguments -s -C \
        '1:Name of the group to be deleted:__ynh_user_group_list_s' 
}

# (( $+functions[_yunohost_user_group_info] )) ||
function _yunohost_user_group_info() {
    _arguments -s -C \
        '1:Name of the group to fetch info about:__ynh_user_group_list_s' 
}

# (( $+functions[_yunohost_user_group_add] )) ||
function _yunohost_user_group_add() {
    _arguments -s -C \
        '1:Name of the group to add user(s) to:__ynh_user_group_list_s' \
        '*:User(s) to add in the group:__ynh_user_list_fields_username' 
}

# (( $+functions[_yunohost_user_group_remove] )) ||
function _yunohost_user_group_remove() {
    _arguments -s -C \
        '1:Name of the group to remove user(s) from:__ynh_user_group_list_s' \
        '*:User(s) to remove from the group:__ynh_user_list_fields_username' 
}

# (( $+functions[_yunohost_user_group_add-mailalias] )) ||
function _yunohost_user_group_add-mailalias() {
    _arguments -s -C \
        '1:Name of the group to add user(s) to:__ynh_user_group_list_s' \
        ''{2,*}':Mail aliases to add:' \
        '--force[Ignore warnings about special groups]' 
}

# (( $+functions[_yunohost_user_group_remove-mailalias] )) ||
function _yunohost_user_group_remove-mailalias() {
    _arguments -s -C \
        '1:Name of the group to add user(s) to:__ynh_user_group_list_s' \
        ''{2,*}':Mail aliases to remove:' \
        '--force[Ignore warnings about special groups]' 
}


#-----------------------------------------
#               user_permission
#-----------------------------------------

# (( $+functions[_yunohost_user_permission] )) ||
function _yunohost_user_permission() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_user_permission; yunohost_user_permission=(
            'list:List permissions and corresponding accesses'
            'info:Get information about a specific permission'
            'update:Manage group or user permissions'
            'add:Grant permission to group or user'
            'remove:Revoke permission to group or user'
            'ldapsync:Resynchronize permissions to LDAP from app settings. This is a purely technical command, only meant to be ran if you manually modified permission settings in app, which is absolutely not recommended.'
        )
        _describe -V -t yunohost-user_permission 'yunohost user_permission category' yunohost_user_permission "$@"
        
    fi
}



# (( $+functions[_yunohost_user_permission_list] )) ||
function _yunohost_user_permission_list() {
    _arguments -s -C \
        '*:Apps to list permission for (all by default):__ynh_app_list' \
        '(-f --full)'{-f,--full}'[Display all info known about each permission, including the full user list of each group it is granted to.]' 
}

# (( $+functions[_yunohost_user_permission_info] )) ||
function _yunohost_user_permission_info() {
    _arguments -s -C \
        '1:Name of the permission to fetch info about (use "yunohost user permission list" and "yunohost user permission -f" to see all the current permissions):__ynh_user_permission_list' 
}

# (( $+functions[_yunohost_user_permission_update] )) ||
function _yunohost_user_permission_update() {
    _arguments -s -C \
        '1:Permission to manage (e.g. mail or nextcloud or wordpress.editors) (use "yunohost user permission list" and "yunohost user permission -f" to see all the current permissions):__ynh_user_permission_list' \
        '(-l --label)'{-l,--label}'[Custom label for this app / permission]:label:' \
        '(-s --show_tile)'{-s,--show_tile}'[Define if a tile will be shown in the user portal]:show_tile:(True False)' \
        '(-L --logo)'{-L,--logo}'[File to use as logo for this app / permission. Only PNG are supported.]:logo:' \
        '(-d --description)'{-d,--description}'[Custom description for this app / permission]:description:' \
        '(-o --order)'{-o,--order}'[Order number to be used when displaying the tiles in the user portal. Default is 100 so set this to any low value for the tile to appear first, or higher value to appear last.]:order:' \
        '(-H --hide_from_public)'{-H,--hide_from_public}'[Mark the tile as to be hidden from the '"'"'public app list'"'"' (if enabled). Useful for apps such as Nextcloud that need to be exposed to be publicly exposed for desktop/mobile client to be able to connect to, but not meant to be listed for visitors.]:hide_from_public:(True False)' 
}

# (( $+functions[_yunohost_user_permission_add] )) ||
function _yunohost_user_permission_add() {
    _arguments -s -C \
        '1:Permission to manage (e.g. mail or nextcloud or wordpress.editors) (use "yunohost user permission list" and "yunohost user permission -f" to see all the current permissions):__ynh_user_permission_list' \
        '*:Group or usernames to grant this permission to:__ynh_user_group_list' 
}

# (( $+functions[_yunohost_user_permission_remove] )) ||
function _yunohost_user_permission_remove() {
    _arguments -s -C \
        '1:Permission to manage (e.g. mail or nextcloud or wordpress.editors) (use "yunohost user permission list" and "yunohost user permission -f" to see all the current permissions):__ynh_user_permission_list' \
        '*:Group or usernames to revoke this permission to:__ynh_user_group_list' 
}

# (( $+functions[_yunohost_user_permission_ldapsync] )) ||
function _yunohost_user_permission_ldapsync() { }


#-----------------------------------------
#               user_ssh
#-----------------------------------------

# (( $+functions[_yunohost_user_ssh] )) ||
function _yunohost_user_ssh() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_user_ssh; yunohost_user_ssh=(
            'list-keys:Show user'"'"'s authorized ssh keys'
            'add-key:Add a new authorized ssh key for this user'
            'remove-key:Remove an authorized ssh key for this user'
        )
        _describe -V -t yunohost-user_ssh 'yunohost user_ssh category' yunohost_user_ssh "$@"
        
    fi
}



# (( $+functions[_yunohost_user_ssh_list-keys] )) ||
function _yunohost_user_ssh_list-keys() {
    _arguments -s -C \
        '1:Username of the user:__ynh_user_list_fields_username' 
}

# (( $+functions[_yunohost_user_ssh_add-key] )) ||
function _yunohost_user_ssh_add-key() {
    _arguments -s -C \
        '1:Username of the user:__ynh_user_list_fields_username' \
        '2:The key to be added:' \
        '(-c --comment)'{-c,--comment}'[Optional comment about the key]:comment:' 
}

# (( $+functions[_yunohost_user_ssh_remove-key] )) ||
function _yunohost_user_ssh_remove-key() {
    _arguments -s -C \
        '1:Username of the user:__ynh_user_list_fields_username' \
        '2:The key to be removed:' 
}


#-----------------------------------------
#               domain
#-----------------------------------------

# (( $+functions[_yunohost_domain] )) ||
function _yunohost_domain() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_domain; yunohost_domain=(
            'list:List domains'
            'info:Get domain aggredated data'
            'add:Create a custom domain'
            'remove:Delete domains'
            'main-domain:Check the current main domain, or change it'
        )
        _describe -V -t yunohost-domain 'yunohost domain category' yunohost_domain "$@"
        
        local -a yunohost_domain_subcategories; yunohost_domain_subcategories=(
            'dyndns:Subscribe and Update DynDNS Hosts'
            'config:Domain settings'
            'dns:Manage domains DNS'
            'cert:Manage domain certificates'
        )
        _describe -V -t yunohost-domain-subcategories 'yunohost domain subcategories' yunohost_domain_subcategories "$@"
    fi
}



# (( $+functions[_yunohost_domain_list] )) ||
function _yunohost_domain_list() {
    _arguments -s -C \
        '--exclude-subdomains[Filter out domains that are obviously subdomains of other declared domains]' \
        '--tree[Display domains as a tree]' \
        '(*)--features[List only domains with features enabled (mail_in, mail_out)]:*:features:' 
}

# (( $+functions[_yunohost_domain_info] )) ||
function _yunohost_domain_info() {
    _arguments -s -C \
        '1:Domain to check:__ynh_domain_list' 
}

# (( $+functions[_yunohost_domain_add] )) ||
function _yunohost_domain_add() {
    _arguments -s -C \
        '1:Domain name to add:' \
        '--ignore-dyndns[If adding a DynDNS domain, only add the domain, without subscribing to the DynDNS service]' \
        '--dyndns-recovery-password[If adding a DynDNS domain, subscribe to the DynDNS service with a password, used to later delete the domain]:dyndns-recovery-password:' \
        '--install-letsencrypt-cert[If adding a subdomain of an already added domain, try to install a Let'"'"'s Encrypt certificate]' 
}

# (( $+functions[_yunohost_domain_remove] )) ||
function _yunohost_domain_remove() {
    _arguments -s -C \
        '1:Domain to delete:__ynh_domain_list' \
        '(-r --remove-apps)'{-r,--remove-apps}'[Remove apps installed on the domain]' \
        '(-f --force)'{-f,--force}'[Do not ask confirmation to remove apps]' \
        '--ignore-dyndns[If removing a DynDNS domain, only remove the domain, without unsubscribing from the DynDNS service]' \
        '--dyndns-recovery-password[If removing a DynDNS domain, unsubscribe from the DynDNS service with a password]:dyndns-recovery-password:' 
}

# (( $+functions[_yunohost_domain_main-domain] )) ||
function _yunohost_domain_main-domain() {
    _arguments -s -C \
        '(-n --new-main-domain)'{-n,--new-main-domain}'[Change the current main domain]:new-main-domain:__ynh_domain_list' 
}


#-----------------------------------------
#               domain_dyndns
#-----------------------------------------

# (( $+functions[_yunohost_domain_dyndns] )) ||
function _yunohost_domain_dyndns() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_domain_dyndns; yunohost_domain_dyndns=(
            'subscribe:Subscribe to a DynDNS service'
            'unsubscribe:Unsubscribe from a DynDNS service'
            'set-recovery-password:Set recovery password'
        )
        _describe -V -t yunohost-domain_dyndns 'yunohost domain_dyndns category' yunohost_domain_dyndns "$@"
        
    fi
}



# (( $+functions[_yunohost_domain_dyndns_subscribe] )) ||
function _yunohost_domain_dyndns_subscribe() {
    _arguments -s -C \
        '1:Domain to subscribe to the DynDNS service:__ynh_domain_list' \
        '(-p --recovery-password)'{-p,--recovery-password}'[Password used to later recover the domain if needed]:recovery-password:' 
}

# (( $+functions[_yunohost_domain_dyndns_unsubscribe] )) ||
function _yunohost_domain_dyndns_unsubscribe() {
    _arguments -s -C \
        '1:Domain to unsubscribe from the DynDNS service:__ynh_domain_list' \
        '(-p --recovery-password)'{-p,--recovery-password}'[Recovery password used to delete the domain]:recovery-password:' 
}

# (( $+functions[_yunohost_domain_dyndns_set-recovery-password] )) ||
function _yunohost_domain_dyndns_set-recovery-password() {
    _arguments -s -C \
        '1:Domain to set recovery password for:__ynh_domain_list' \
        '(-p --recovery-password)'{-p,--recovery-password}'[The new recovery password]:recovery-password:' 
}


#-----------------------------------------
#               domain_config
#-----------------------------------------

# (( $+functions[_yunohost_domain_config] )) ||
function _yunohost_domain_config() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_domain_config; yunohost_domain_config=(
            'get:Display a domain configuration'
            'set:Apply a new configuration'
        )
        _describe -V -t yunohost-domain_config 'yunohost domain_config category' yunohost_domain_config "$@"
        
    fi
}



# (( $+functions[_yunohost_domain_config_get] )) ||
function _yunohost_domain_config_get() {
    _arguments -s -C \
        '1:Domain name:__ynh_domain_list' \
        '2:A specific panel, section or a question identifier:' \
        '(-f --full)'{-f,--full}'[Display all details (meant to be used by the API)]' \
        '(-e --export)'{-e,--export}'[Only export key/values, meant to be reimported using "config set --args-file"]' 
}

# (( $+functions[_yunohost_domain_config_set] )) ||
function _yunohost_domain_config_set() {
    _arguments -s -C \
        '1:Domain name:__ynh_domain_list' \
        '2:The question or form key:' \
        '(-v --value)'{-v,--value}'[new value]:value:' \
        '(-a --args)'{-a,--args}'[Serialized arguments for new configuration (i.e. "mail_in=0&mail_out=0")]:args:' 
}


#-----------------------------------------
#               domain_dns
#-----------------------------------------

# (( $+functions[_yunohost_domain_dns] )) ||
function _yunohost_domain_dns() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_domain_dns; yunohost_domain_dns=(
            'suggest:Generate sample DNS configuration for a domain'
            'push:Push DNS records to registrar'
        )
        _describe -V -t yunohost-domain_dns 'yunohost domain_dns category' yunohost_domain_dns "$@"
        
    fi
}



# (( $+functions[_yunohost_domain_dns_suggest] )) ||
function _yunohost_domain_dns_suggest() {
    _arguments -s -C \
        '1:Target domain:__ynh_domain_list' 
}

# (( $+functions[_yunohost_domain_dns_push] )) ||
function _yunohost_domain_dns_push() {
    _arguments -s -C \
        '1:Domain name to push DNS conf for:__ynh_domain_list' \
        '(-d --dry-run)'{-d,--dry-run}'[Only display what'"'"'s to be pushed]' \
        '--force[Also update/remove records which were not originally set by Yunohost, or which have been manually modified]' \
        '--purge[Delete all records]' 
}


#-----------------------------------------
#               domain_cert
#-----------------------------------------

# (( $+functions[_yunohost_domain_cert] )) ||
function _yunohost_domain_cert() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_domain_cert; yunohost_domain_cert=(
            'status:List status of current certificates (all by default).'
            'install:Install Let'"'"'s Encrypt certificates for given domains (all by default).'
            'renew:Renew the Let'"'"'s Encrypt certificates for given domains (all by default).'
        )
        _describe -V -t yunohost-domain_cert 'yunohost domain_cert category' yunohost_domain_cert "$@"
        
    fi
}



# (( $+functions[_yunohost_domain_cert_status] )) ||
function _yunohost_domain_cert_status() {
    _arguments -s -C \
        '*:Domains to check:__ynh_domain_list' \
        '--full[Show more details]' 
}

# (( $+functions[_yunohost_domain_cert_install] )) ||
function _yunohost_domain_cert_install() {
    _arguments -s -C \
        '*:Domains for which to install the certificates:__ynh_domain_list' \
        '--force[Install even if current certificate is not self-signed]' \
        '--no-checks[Does not perform any check that your domain seems correctly configured (DNS, reachability) before attempting to install. (Not recommended)]' \
        '--self-signed[Install self-signed certificate instead of Let'"'"'s Encrypt]' 
}

# (( $+functions[_yunohost_domain_cert_renew] )) ||
function _yunohost_domain_cert_renew() {
    _arguments -s -C \
        '*:Domains for which to renew the certificates:__ynh_domain_list' \
        '--force[Ignore the validity threshold (15 days)]' \
        '--email[Send an email to root with logs if some renewing fails]' \
        '--no-checks[Does not perform any check that your domain seems correctly configured (DNS, reachability) before attempting to renew. (Not recommended)]' 
}


#-----------------------------------------
#               app
#-----------------------------------------

# (( $+functions[_yunohost_app] )) ||
function _yunohost_app() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_app; yunohost_app=(
            'catalog:Show the catalog of installable application'
            'search:Search installable apps'
            'manifest:Return the manifest of a given app from the catalog, or from a remote git repo'
            'list:List installed apps'
            'info:Show infos about a specific installed app'
            'map:Show the mapping between urls and apps'
            'install:Install apps'
            'remove:Remove app'
            'upgrade:Upgrade app'
            'change-url:Change app'"'"'s URL'
            'setting:Set or get an app setting value'
            'shell:Open an interactive shell with the app environment already loaded'
            'ssowatconf:Regenerate SSOwat configuration file'
            'change-label:Change app label'
        )
        _describe -V -t yunohost-app 'yunohost app category' yunohost_app "$@"
        
        local -a yunohost_app_subcategories; yunohost_app_subcategories=(
            'action:Handle apps actions'
            'config:Applications configuration panel'
        )
        _describe -V -t yunohost-app-subcategories 'yunohost app subcategories' yunohost_app_subcategories "$@"
    fi
}



# (( $+functions[_yunohost_app_catalog] )) ||
function _yunohost_app_catalog() {
    _arguments -s -C \
        '(-f --full)'{-f,--full}'[Display all details, including the app manifest and various other infos]' \
        '(-c --with-categories)'{-c,--with-categories}'[Also return a list of app categories]' \
        '(-a --with-antifeatures)'{-a,--with-antifeatures}'[Also return a list of antifeatures categories]' 
}

# (( $+functions[_yunohost_app_search] )) ||
function _yunohost_app_search() {
    _arguments -s -C \
        '1:Return matching app name or description with "string":' 
}

# (( $+functions[_yunohost_app_manifest] )) ||
function _yunohost_app_manifest() {
    _arguments -s -C \
        '1:Name, local path or git URL of the app to fetch the manifest of:__ynh_app_catalog' \
        '(-s --with-screenshot)'{-s,--with-screenshot}'[Also return a base64 screenshot if any (API only)]' 
}

# (( $+functions[_yunohost_app_list] )) ||
function _yunohost_app_list() {
    _arguments -s -C \
        '(-f --full)'{-f,--full}'[Display all details, including the app manifest and various other infos]' 
}

# (( $+functions[_yunohost_app_info] )) ||
function _yunohost_app_info() {
    _arguments -s -C \
        '1:Specific app ID:__ynh_app_list' \
        '(-f --full)'{-f,--full}'[Display all details, including the app manifest and various other infos]' \
        '--with-pre-upgrade-notifications[Also fetch pre-upgrade notifications, if an upgrade is available (this is meant for the web API)]' 
}

# (( $+functions[_yunohost_app_map] )) ||
function _yunohost_app_map() {
    _arguments -s -C \
        '(-a --app)'{-a,--app}'[Specific app to map]:app:__ynh_app_list' \
        '(-r --raw)'{-r,--raw}'[Return complete dict]' \
        '(-u --user)'{-u,--user}'[Allowed app map for a user]:user:__ynh_user_list_fields_username' 
}

# (( $+functions[_yunohost_app_install] )) ||
function _yunohost_app_install() {
    _arguments -s -C \
        '1:Name, local path or git URL of the app to install:__ynh_app_catalog' \
        '(-l --label)'{-l,--label}'[Custom name for the app]:label:' \
        '(-a --args)'{-a,--args}'[Serialized arguments for app script (i.e. "domain=domain.tld&path=/path&init_main_permission=visitors")]:args:' \
        '(-n --no-remove-on-failure)'{-n,--no-remove-on-failure}'[Debug option to avoid removing the app on a failed installation]' \
        '(-f --force)'{-f,--force}'[Do not ask confirmation if the app is not safe to use (low quality, experimental or 3rd party), or when the app displays a post-install notification]' \
        '(-i --ignore-yunohost-version)'{-i,--ignore-yunohost-version}'[Attempt to install the app even if your YunoHost version is below the required one]' 
}

# (( $+functions[_yunohost_app_remove] )) ||
function _yunohost_app_remove() {
    _arguments -s -C \
        '1:App to remove:__ynh_app_list' \
        '(-p --purge)'{-p,--purge}'[Also remove all application data]' 
}

# (( $+functions[_yunohost_app_upgrade] )) ||
function _yunohost_app_upgrade() {
    _arguments -s -C \
        '*:App(s) to upgrade (default all):__ynh_app_list' \
        '(-u --url)'{-u,--url}'[Git url to fetch for upgrade]:url:' \
        '(-f --file)'{-f,--file}'[Folder or tarball for upgrade]:file:' \
        '(-F --force)'{-F,--force}'[Force the update, even though the app is up to date]' \
        '(-b --no-safety-backup)'{-b,--no-safety-backup}'[Disable the safety backup during upgrade]' \
        '(-c --continue-on-failure)'{-c,--continue-on-failure}'[Continue to upgrade apps even if one or more upgrade failed]' \
        '(-i --ignore-yunohost-version)'{-i,--ignore-yunohost-version}'[Attempt to upgrade the app even if your YunoHost version is below the required one]' 
}

# (( $+functions[_yunohost_app_change-url] )) ||
function _yunohost_app_change-url() {
    _arguments -s -C \
        '1:Target app instance name:__ynh_app_list' \
        '(-d --domain)'{-d,--domain}'[New app domain on which the application will be moved]:domain:__ynh_domain_list' \
        '(-p --path)'{-p,--path}'[New path at which the application will be moved]:path:' 
}

# (( $+functions[_yunohost_app_setting] )) ||
function _yunohost_app_setting() {
    _arguments -s -C \
        '1:App ID:__ynh_app_list' \
        '2:Key to get/set:' \
        '(-v --value)'{-v,--value}'[Value to set]:value:' \
        '(-d --delete)'{-d,--delete}'[Delete the key]' 
}

# (( $+functions[_yunohost_app_shell] )) ||
function _yunohost_app_shell() {
    _arguments -s -C \
        '1:App ID:__ynh_app_list' 
}

# (( $+functions[_yunohost_app_ssowatconf] )) ||
function _yunohost_app_ssowatconf() { }

# (( $+functions[_yunohost_app_change-label] )) ||
function _yunohost_app_change-label() {
    _arguments -s -C \
        '1:App ID:__ynh_app_list' \
        '2:New app label:' 
}


#-----------------------------------------
#               app_action
#-----------------------------------------

# (( $+functions[_yunohost_app_action] )) ||
function _yunohost_app_action() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_app_action; yunohost_app_action=(
            'list:List app actions'
            'run:Run app action'
        )
        _describe -V -t yunohost-app_action 'yunohost app_action category' yunohost_app_action "$@"
        
    fi
}



# (( $+functions[_yunohost_app_action_list] )) ||
function _yunohost_app_action_list() {
    _arguments -s -C \
        '1:App name:__ynh_app_list' 
}

# (( $+functions[_yunohost_app_action_run] )) ||
function _yunohost_app_action_run() {
    _arguments -s -C \
        '1:App name:__ynh_app_list' \
        '2:action id:' \
        '(-a --args)'{-a,--args}'[Serialized arguments for app script (i.e. "domain=domain.tld&path=/path")]:args:' 
}


#-----------------------------------------
#               app_config
#-----------------------------------------

# (( $+functions[_yunohost_app_config] )) ||
function _yunohost_app_config() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_app_config; yunohost_app_config=(
            'get:Display an app configuration'
            'set:Apply a new configuration'
        )
        _describe -V -t yunohost-app_config 'yunohost app_config category' yunohost_app_config "$@"
        
    fi
}



# (( $+functions[_yunohost_app_config_get] )) ||
function _yunohost_app_config_get() {
    _arguments -s -C \
        '1:App name:__ynh_app_list' \
        '2:A specific panel, section or a question identifier:' \
        '(-f --full)'{-f,--full}'[Display all details (meant to be used by the API)]' \
        '(-e --export)'{-e,--export}'[Only export key/values, meant to be reimported using "config set --args-file"]' \
        '--core[Get the '"'"'core'"'"' config for this app, such as permissions stuff. This option is only meant for API.]' 
}

# (( $+functions[_yunohost_app_config_set] )) ||
function _yunohost_app_config_set() {
    _arguments -s -C \
        '1:App name:__ynh_app_list' \
        '2:The question or panel key:' \
        '(-v --value)'{-v,--value}'[new value]:value:' \
        '(-a --args)'{-a,--args}'[Serialized arguments for new configuration (i.e. "domain=domain.tld&path=/path")]:args:' \
        '(-f --args-file)'{-f,--args-file}'[YAML or JSON file with key/value couples]:args-file:' \
        '--core[Set the '"'"'core'"'"' config for this app, such as permissions stuff. This option is only meant for API.]' 
}


#-----------------------------------------
#               backup
#-----------------------------------------

# (( $+functions[_yunohost_backup] )) ||
function _yunohost_backup() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_backup; yunohost_backup=(
            'create:Create a backup local archive. If neither --apps or --system are given, this will backup all apps and all system parts. If only --apps if given, this will only backup apps and no system parts. Similarly, if only --system is given, this will only backup system parts and no apps.'
            'restore:Restore from a local backup archive. If neither --apps or --system are given, this will restore all apps and all system parts in the archive. If only --apps if given, this will only restore apps and no system parts. Similarly, if only --system is given, this will only restore system parts and no apps.'
            'list:List available local backup archives'
            'info:Show info about a local backup archive'
            'delete:Delete a backup archive'
        )
        _describe -V -t yunohost-backup 'yunohost backup category' yunohost_backup "$@"
        
    fi
}



# (( $+functions[_yunohost_backup_create] )) ||
function _yunohost_backup_create() {
    _arguments -s -C \
        '(-n --name)'{-n,--name}'[Name of the backup archive]:name:' \
        '(-d --description)'{-d,--description}'[Short description of the backup]:description:' \
        '(-o --output-directory)'{-o,--output-directory}'[Output directory for the backup]:output-directory:' \
        '(*)--methods[List of backup methods to apply (copy or tar by default)]:*:methods:' \
        '(*)--system[List of system parts to backup (or all if none given).]:*:system:' \
        '(*)--apps[List of application names to backup (or all if none given)]:*:apps:__ynh_app_list' \
        '--dry-run['"'"'Simulate'"'"' the backup and return the size details per item to backup]' 
}

# (( $+functions[_yunohost_backup_restore] )) ||
function _yunohost_backup_restore() {
    _arguments -s -C \
        '1:Name or path of the backup archive:__ynh_backup_list' \
        '(*)--system[List of system parts to restore (or all if none is given)]:*:system:' \
        '(*)--apps[List of application names to restore (or all if none is given)]:*:apps:__ynh_app_list' \
        '--force[Force restauration on an already installed system]' \
        '--no-remove-on-failure[For app only, debug option to avoid removing the app on a failed restore]' 
}

# (( $+functions[_yunohost_backup_list] )) ||
function _yunohost_backup_list() {
    _arguments -s -C \
        '(-i --with-info)'{-i,--with-info}'[Show backup information for each archive]' \
        '(-H --human-readable)'{-H,--human-readable}'[Print sizes in human readable format]' 
}

# (( $+functions[_yunohost_backup_info] )) ||
function _yunohost_backup_info() {
    _arguments -s -C \
        '1:Name or path of the backup archive:__ynh_backup_list' \
        '(-d --with-details)'{-d,--with-details}'[Show additional backup information]' \
        '(-H --human-readable)'{-H,--human-readable}'[Print sizes in human readable format]' 
}

# (( $+functions[_yunohost_backup_delete] )) ||
function _yunohost_backup_delete() {
    _arguments -s -C \
        '1:Name of the archive to delete:__ynh_backup_list' 
}


#-----------------------------------------
#               settings
#-----------------------------------------

# (( $+functions[_yunohost_settings] )) ||
function _yunohost_settings() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_settings; yunohost_settings=(
            'list:list all entries of the settings'
            'get:get an entry value in the settings'
            'set:set an entry value in the settings'
            'reset-all:reset all settings to their default value'
            'reset:set an entry value to its default one'
        )
        _describe -V -t yunohost-settings 'yunohost settings category' yunohost_settings "$@"
        
    fi
}



# (( $+functions[_yunohost_settings_list] )) ||
function _yunohost_settings_list() {
    _arguments -s -C \
        '(-f --full)'{-f,--full}'[Display all details (meant to be used by the API)]' 
}

# (( $+functions[_yunohost_settings_get] )) ||
function _yunohost_settings_get() {
    _arguments -s -C \
        '1:Settings key:__ynh_settings_list' \
        '(-f --full)'{-f,--full}'[Display all details (meant to be used by the API)]' \
        '(-e --export)'{-e,--export}'[Only export key/values, meant to be reimported using "config set --args-file"]' 
}

# (( $+functions[_yunohost_settings_set] )) ||
function _yunohost_settings_set() {
    _arguments -s -C \
        '1:The question or form key:__ynh_settings_list' \
        '(-v --value)'{-v,--value}'[new value]:value:' \
        '(-a --args)'{-a,--args}'[Serialized arguments for new configuration (i.e. "mail_in=0&mail_out=0")]:args:' 
}

# (( $+functions[_yunohost_settings_reset-all] )) ||
function _yunohost_settings_reset-all() { }

# (( $+functions[_yunohost_settings_reset] )) ||
function _yunohost_settings_reset() {
    _arguments -s -C \
        '1:Settings key:__ynh_settings_list' 
}


#-----------------------------------------
#               service
#-----------------------------------------

# (( $+functions[_yunohost_service] )) ||
function _yunohost_service() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_service; yunohost_service=(
            'add:Add a service'
            'remove:Remove a service'
            'start:Start one or more services'
            'stop:Stop one or more services'
            'reload:Reload one or more services'
            'restart:Restart one or more services. If the services are not running yet, they will be started.'
            'reload_or_restart:Reload one or more services if they support it. If not, restart them instead. If the services are not running yet, they will be started.'
            'enable:Enable one or more services'
            'disable:Disable one or more services'
            'status:Show status information about one or more services (all by default)'
            'log:Log every log files of a service'
        )
        _describe -V -t yunohost-service 'yunohost service category' yunohost_service "$@"
        
    fi
}



# (( $+functions[_yunohost_service_add] )) ||
function _yunohost_service_add() {
    _arguments -s -C \
        '1:Service name to add:' \
        '(-d --description)'{-d,--description}'[Description of the service]:description:' \
        '(* -l --log)'{-l,--log}'[Absolute path to log file to display]:*:log:_files' \
        '--test_status[Specify a custom bash command to check the status of the service. Note that it only makes sense to specify this if the corresponding systemd service does not return the proper information already.]:test_status:' \
        '--test_conf[Specify a custom bash command to check if the configuration of the service is valid or broken, similar to nginx -t.]:test_conf:' \
        '(*)--needs_exposed_ports[A list of ports that needs to be publicly exposed for the service to work as intended.]:*:needs_exposed_ports:' \
        '(-n --need_lock)'{-n,--need_lock}'[Use this option to prevent deadlocks if the service does invoke yunohost commands.]' 
}

# (( $+functions[_yunohost_service_remove] )) ||
function _yunohost_service_remove() {
    _arguments -s -C \
        '1:Service name to remove:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_start] )) ||
function _yunohost_service_start() {
    _arguments -s -C \
        ''{1,*}':Service name to start:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_stop] )) ||
function _yunohost_service_stop() {
    _arguments -s -C \
        ''{1,*}':Service name to stop:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_reload] )) ||
function _yunohost_service_reload() {
    _arguments -s -C \
        ''{1,*}':Service name to reload:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_restart] )) ||
function _yunohost_service_restart() {
    _arguments -s -C \
        ''{1,*}':Service name to restart:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_reload_or_restart] )) ||
function _yunohost_service_reload_or_restart() {
    _arguments -s -C \
        ''{1,*}':Service name to reload or restart:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_enable] )) ||
function _yunohost_service_enable() {
    _arguments -s -C \
        ''{1,*}':Service name to enable:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_disable] )) ||
function _yunohost_service_disable() {
    _arguments -s -C \
        ''{1,*}':Service name to disable:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_status] )) ||
function _yunohost_service_status() {
    _arguments -s -C \
        '*:Service name to show:__ynh_service_status' 
}

# (( $+functions[_yunohost_service_log] )) ||
function _yunohost_service_log() {
    _arguments -s -C \
        '1:Service name to log:__ynh_service_status' \
        '(-n --number)'{-n,--number}'[Number of lines to display]:number:' 
}


#-----------------------------------------
#               firewall
#-----------------------------------------

# (( $+functions[_yunohost_firewall] )) ||
function _yunohost_firewall() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_firewall; yunohost_firewall=(
            'list:List all firewall rules'
            'is-open:Returns whether the port is open or not.'
            'open:Allow connections on a port'
            'close:Disallow connections on a port'
            'delete:Unregister a port from YunoHost'
            'allow:Allow connections on a port'
            'disallow:Disallow connections on a port'
            'upnp:Manage port forwarding using UPnP'
            'reload:Reload all firewall rules'
            'stop:Remove all the firewall rules'
        )
        _describe -V -t yunohost-firewall 'yunohost firewall category' yunohost_firewall "$@"
        
    fi
}



# (( $+functions[_yunohost_firewall_list] )) ||
function _yunohost_firewall_list() {
    _arguments -s -C \
        '(-r --raw)'{-r,--raw}'[Return the complete YAML dict]' \
        '(-p --protocol)'{-p,--protocol}'[If not raw, protocol type to list (tcp/udp)]:protocol:(tcp udp)' \
        '(-f --forwarded)'{-f,--forwarded}'[If not raw, list UPnP forwarded ports instead of open ports]' 
}

# (( $+functions[_yunohost_firewall_is-open] )) ||
function _yunohost_firewall_is-open() {
    _arguments -s -C \
        '1:Port or range of ports to check:' \
        '(-p --protocol)'{-p,--protocol}'[Protocol type (tcp/udp)]:protocol:(tcp udp)' 
}

# (( $+functions[_yunohost_firewall_open] )) ||
function _yunohost_firewall_open() {
    _arguments -s -C \
        '1:Port or range of ports to open:' \
        '(-p --protocol)'{-p,--protocol}'[Protocol type (tcp/udp)]:protocol:(tcp udp)' \
        '2:A reason for the port to be open (like the app'"'"'s name) (default\: ):' \
        '--upnp[Add forwarding of this port with UPnP]' \
        '--no-reload[Do not reload firewall rules]' 
}

# (( $+functions[_yunohost_firewall_close] )) ||
function _yunohost_firewall_close() {
    _arguments -s -C \
        '1:Port or range of ports to close:' \
        '(-p --protocol)'{-p,--protocol}'[Protocol type (tcp/udp)]:protocol:(tcp udp)' \
        '--upnp-only[Only remove forwarding of this port with UPnP]' \
        '--no-reload[Do not reload firewall rules]' 
}

# (( $+functions[_yunohost_firewall_delete] )) ||
function _yunohost_firewall_delete() {
    _arguments -s -C \
        '1:Port or range of ports to delete:' \
        '(-p --protocol)'{-p,--protocol}'[Protocol type (tcp/udp)]:protocol:(tcp udp)' \
        '--no-reload[Do not reload firewall rules]' 
}

# (( $+functions[_yunohost_firewall_allow] )) ||
function _yunohost_firewall_allow() {
    _arguments -s -C \
        '1:Protocol type to allow (TCP/UDP/Both) (default\: TCP):(TCP UDP Both)' \
        '2:Port or range of ports to open:' \
        '(-4 --ipv4-only)'{-4,--ipv4-only}'[Only add a rule for IPv4 connections]' \
        '(-6 --ipv6-only)'{-6,--ipv6-only}'[Only add a rule for IPv6 connections]' \
        '--no-upnp[Do not add forwarding of this port with UPnP]' \
        '--no-reload[Do not reload firewall rules]' 
}

# (( $+functions[_yunohost_firewall_disallow] )) ||
function _yunohost_firewall_disallow() {
    _arguments -s -C \
        '1:Protocol type to allow (TCP/UDP/Both) (default\: TCP):(TCP UDP Both)' \
        '2:Port or range of ports to close:' \
        '(-4 --ipv4-only)'{-4,--ipv4-only}'[Only remove the rule for IPv4 connections]' \
        '(-6 --ipv6-only)'{-6,--ipv6-only}'[Only remove the rule for IPv6 connections]' \
        '--upnp-only[Only remove forwarding of this port with UPnP]' \
        '--no-reload[Do not reload firewall rules]' 
}

# (( $+functions[_yunohost_firewall_upnp] )) ||
function _yunohost_firewall_upnp() {
    _arguments -s -C \
        '1:action (default\: status):(enable disable status)' \
        '--no-refresh[Do not refresh port forwarding]' 
}

# (( $+functions[_yunohost_firewall_reload] )) ||
function _yunohost_firewall_reload() {
    _arguments -s -C \
        '--skip-upnp[Do not refresh port forwarding using UPnP]' 
}

# (( $+functions[_yunohost_firewall_stop] )) ||
function _yunohost_firewall_stop() { }


#-----------------------------------------
#               dyndns
#-----------------------------------------

# (( $+functions[_yunohost_dyndns] )) ||
function _yunohost_dyndns() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_dyndns; yunohost_dyndns=(
            'subscribe:Subscribe to a DynDNS service'
            'update:Update IP on DynDNS platform'
        )
        _describe -V -t yunohost-dyndns 'yunohost dyndns category' yunohost_dyndns "$@"
        
    fi
}



# (( $+functions[_yunohost_dyndns_subscribe] )) ||
function _yunohost_dyndns_subscribe() {
    _arguments -s -C \
        '(-d --domain)'{-d,--domain}'[Full domain to subscribe with ( deprecated, use '"'"'yunohost domain dyndns subscribe'"'"' instead )]:domain:__ynh_domain_list' \
        '(-p --recovery-password)'{-p,--recovery-password}'[Password used to later recover the domain if needed]:recovery-password:' 
}

# (( $+functions[_yunohost_dyndns_update] )) ||
function _yunohost_dyndns_update() {
    _arguments -s -C \
        '(-d --domain)'{-d,--domain}'[Full domain to update]:domain:__ynh_domain_list' \
        '(-f --force)'{-f,--force}'[Force the update (for debugging only)]' \
        '(-D --dry-run)'{-D,--dry-run}'[Only display the generated zone]' \
        '--email[Send an email to root with logs if some updating fails]' 
}


#-----------------------------------------
#               tools
#-----------------------------------------

# (( $+functions[_yunohost_tools] )) ||
function _yunohost_tools() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_tools; yunohost_tools=(
            'rootpw:Change root password'
            'maindomain:Check the current main domain, or change it'
            'postinstall:YunoHost post-install'
            'update:YunoHost update'
            'upgrade:YunoHost upgrade'
            'shell:Launch a development shell'
            'basic-space-cleanup:Basic space cleanup (apt, journalctl, system and YunoHost logs, ...)'
            'shutdown:Shutdown the server'
            'reboot:Reboot the server'
            'regen-conf:Regenerate the configuration file(s)'
            'versions:Display YunoHost'"'"'s packages versions'
        )
        _describe -V -t yunohost-tools 'yunohost tools category' yunohost_tools "$@"
        
        local -a yunohost_tools_subcategories; yunohost_tools_subcategories=(
            'migrations:Manage migrations'
        )
        _describe -V -t yunohost-tools-subcategories 'yunohost tools subcategories' yunohost_tools_subcategories "$@"
    fi
}



# (( $+functions[_yunohost_tools_rootpw] )) ||
function _yunohost_tools_rootpw() {
    _arguments -s -C \
        '(-n --new-password)'{-n,--new-password}'[new-password]:new-password:' 
}

# (( $+functions[_yunohost_tools_maindomain] )) ||
function _yunohost_tools_maindomain() {
    _arguments -s -C \
        '(-n --new-main-domain)'{-n,--new-main-domain}'[Change the current main domain]:new-main-domain:__ynh_domain_list' 
}

# (( $+functions[_yunohost_tools_postinstall] )) ||
function _yunohost_tools_postinstall() {
    _arguments -s -C \
        '(-d --domain)'{-d,--domain}'[YunoHost main domain]:domain:__ynh_domain_list' \
        '(-u --username)'{-u,--username}'[Username for the first (admin) user. For example '"'"'camille'"'"']:username:__ynh_user_list_fields_username' \
        '(-F --fullname)'{-F,--fullname}'[The full name for the first (admin) user. For example '"'"'Camille Dupont'"'"']:fullname:' \
        '(-p --password)'{-p,--password}'[YunoHost admin password]:password:' \
        '--ignore-dyndns[If adding a DynDNS domain, only add the domain, without subscribing to the DynDNS service]' \
        '--dyndns-recovery-password[If adding a DynDNS domain, subscribe to the DynDNS service with a password, used to later recover the domain if needed]:dyndns-recovery-password:' \
        '--force-diskspace[Use this if you really want to install YunoHost on a setup with less than 10 GB on the root filesystem]' \
        '--i-have-read-terms-of-services[Automatically reply to the terms of services prompt, for example for non-interactive installations]' 
}

# (( $+functions[_yunohost_tools_update] )) ||
function _yunohost_tools_update() {
    _arguments -s -C \
        '1:What to update, "apps" (application catalog) or "system" (fetch available package upgrades, equivalent to apt update), "all" for both (default\: all):(apps system all)' \
        '--no-refresh[Does not run apt update or fetch the apps catalog, only list upgradable packages and apps]' 
}

# (( $+functions[_yunohost_tools_upgrade] )) ||
function _yunohost_tools_upgrade() {
    _arguments -s -C \
        '1:What to upgrade, either "apps" (all apps) or "system" (all system packages):(apps system)' 
}

# (( $+functions[_yunohost_tools_shell] )) ||
function _yunohost_tools_shell() {
    _arguments -s -C \
        '(-c --command)'{-c,--command}'[python command to execute]:command:' 
}

# (( $+functions[_yunohost_tools_basic-space-cleanup] )) ||
function _yunohost_tools_basic-space-cleanup() { }

# (( $+functions[_yunohost_tools_shutdown] )) ||
function _yunohost_tools_shutdown() {
    _arguments -s -C \
        '(-f --force)'{-f,--force}'[skip the shutdown confirmation]' 
}

# (( $+functions[_yunohost_tools_reboot] )) ||
function _yunohost_tools_reboot() {
    _arguments -s -C \
        '(-f --force)'{-f,--force}'[skip the reboot confirmation]' 
}

# (( $+functions[_yunohost_tools_regen-conf] )) ||
function _yunohost_tools_regen-conf() {
    _arguments -s -C \
        '*:Categories to regenerate configuration of (all by default):' \
        '(-d --with-diff)'{-d,--with-diff}'[Show differences in case of configuration changes]' \
        '(-f --force)'{-f,--force}'[Override all manual modifications in configuration files]' \
        '(-n --dry-run)'{-n,--dry-run}'[Show what would have been regenerated]' \
        '(-p --list-pending)'{-p,--list-pending}'[List pending configuration files and exit]' 
}

# (( $+functions[_yunohost_tools_versions] )) ||
function _yunohost_tools_versions() { }


#-----------------------------------------
#               tools_migrations
#-----------------------------------------

# (( $+functions[_yunohost_tools_migrations] )) ||
function _yunohost_tools_migrations() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_tools_migrations; yunohost_tools_migrations=(
            'list:List migrations'
            'run:Run migrations'
            'state:Show current migrations state'
        )
        _describe -V -t yunohost-tools_migrations 'yunohost tools_migrations category' yunohost_tools_migrations "$@"
        
    fi
}



# (( $+functions[_yunohost_tools_migrations_list] )) ||
function _yunohost_tools_migrations_list() {
    _arguments -s -C \
        '--pending[list only pending migrations]' \
        '--done[list only migrations already performed]' 
}

# (( $+functions[_yunohost_tools_migrations_run] )) ||
function _yunohost_tools_migrations_run() {
    _arguments -s -C \
        '*:Migrations to run (all pendings by default):__ynh_tools_migrations_list' \
        '--skip[Skip specified migrations (to be used only if you know what you are doing)]' \
        '--force-rerun[Re-run already-ran specified migration (to be used only if you know what you are doing)]' \
        '--auto[Automatic mode, won'"'"'t run manual migrations (to be used only if you know what you are doing)]' \
        '--accept-disclaimer[Accept disclaimers of migrations (please read them before using this option)]' 
}

# (( $+functions[_yunohost_tools_migrations_state] )) ||
function _yunohost_tools_migrations_state() { }


#-----------------------------------------
#               hook
#-----------------------------------------

# (( $+functions[_yunohost_hook] )) ||
function _yunohost_hook() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_hook; yunohost_hook=(
            'add:Store hook script to filesystem'
            'remove:Remove hook scripts from filesystem'
            'info:Get information about a given hook'
            'list:List available hooks for an action'
        )
        _describe -V -t yunohost-hook 'yunohost hook category' yunohost_hook "$@"
        
    fi
}



# (( $+functions[_yunohost_hook_add] )) ||
function _yunohost_hook_add() {
    _arguments -s -C \
        '1:App to link with:__ynh_app_list' \
        '2:Script to add:_files' 
}

# (( $+functions[_yunohost_hook_remove] )) ||
function _yunohost_hook_remove() {
    _arguments -s -C \
        '1:Scripts related to app will be removed:__ynh_app_list' 
}

# (( $+functions[_yunohost_hook_info] )) ||
function _yunohost_hook_info() {
    local context state state_descr line
    typeset -A opt_args
    
    _arguments -s -C \
        '1:Action name:(post_user_create post_user_delete post_user_update post_app_addaccess post_app_removeaccess post_domain_add post_domain_remove post_cert_update custom_dns_rules post_app_change_url post_app_upgrade post_app_install post_app_remove backup restore backup_method post_iptable_rules conf_regen)' \
        '2:Hook name:->name' 

    if (($CURRENT > 2)); then
        case "$state" in
            name)
                local previous="$words[${CURRENT} - 1]"
                local cmd_ret=$(__get_ynh_cache YNH_hook_list_"${previous}" "sudo yunohost hook list ${previous} --output-as json | jq -cr '.hooks[]' | xargs")
                if (( ${#cmd_ret} != 0 )); then
                    local -a cmd_list=("${(s/ /)cmd_ret}")
                    _values 'name' $cmd_list
                fi
                ;;
        esac
    fi
    return $?
}

# (( $+functions[_yunohost_hook_list] )) ||
function _yunohost_hook_list() {
    _arguments -s -C \
        '1:Action name:(post_user_create post_user_delete post_user_update post_app_addaccess post_app_removeaccess post_domain_add post_domain_remove post_cert_update custom_dns_rules post_app_change_url post_app_upgrade post_app_install post_app_remove backup restore backup_method post_iptable_rules conf_regen)' \
        '(-l --list-by)'{-l,--list-by}'[Property to list hook by]:list-by:(name priority folder)' \
        '(-i --show-info)'{-i,--show-info}'[Show hook information]' 
}


#-----------------------------------------
#               log
#-----------------------------------------

# (( $+functions[_yunohost_log] )) ||
function _yunohost_log() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_log; yunohost_log=(
            'list:List logs'
            'show:Display a log content'
            'share:Share the full log on yunopaste (alias to show --share)'
        )
        _describe -V -t yunohost-log 'yunohost log category' yunohost_log "$@"
        
    fi
}



# (( $+functions[_yunohost_log_list] )) ||
function _yunohost_log_list() {
    _arguments -s -C \
        '(-l --limit)'{-l,--limit}'[Maximum number of operations to list (default to 50)]:limit:' \
        '(-d --with-details)'{-d,--with-details}'[Show additional infos (e.g. operation success) but may significantly increase command time. Consider using --limit in combination with this.]' \
        '(-s --with-suboperations)'{-s,--with-suboperations}'[Include metadata about operations that are not the main operation but are sub-operations triggered by another ongoing operation... (e.g. initializing groups/permissions when installing an app)]' 
}

# (( $+functions[_yunohost_log_show] )) ||
function _yunohost_log_show() {
    _arguments -s -C \
        '1:Log file which to display the content:__ynh_log_list' \
        '(-n --number)'{-n,--number}'[Number of lines to display]:number:' \
        '--share[(Deprecated, see yunohost log share) Share the full log using yunopaste]' \
        '(-i --filter-irrelevant)'{-i,--filter-irrelevant}'[Do not show some lines deemed not relevant (like set +x or helper argument parsing)]' \
        '(-s --with-suboperations)'{-s,--with-suboperations}'[Include metadata about sub-operations of this operation... (e.g. initializing groups/permissions when installing an app)]' 
}

# (( $+functions[_yunohost_log_share] )) ||
function _yunohost_log_share() {
    _arguments -s -C \
        '1:Log file to share:__ynh_log_list' 
}


#-----------------------------------------
#               diagnosis
#-----------------------------------------

# (( $+functions[_yunohost_diagnosis] )) ||
function _yunohost_diagnosis() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_diagnosis; yunohost_diagnosis=(
            'list:List diagnosis categories'
            'show:Show most recents diagnosis results'
            'get:Low-level command to fetch raw data and status about a specific diagnosis test'
            'run:Run diagnosis'
            'ignore:Configure some diagnosis results to be ignored and therefore not considered as actual issues'
            'unignore:Configure some diagnosis results to be unignored and therefore considered as actual issues'
        )
        _describe -V -t yunohost-diagnosis 'yunohost diagnosis category' yunohost_diagnosis "$@"
        
    fi
}



# (( $+functions[_yunohost_diagnosis_list] )) ||
function _yunohost_diagnosis_list() { }

# (( $+functions[_yunohost_diagnosis_show] )) ||
function _yunohost_diagnosis_show() {
    _arguments -s -C \
        '*:Diagnosis categories to display (all by default):__ynh_diagnosis_list' \
        '--full[Display additional information]' \
        '--issues[Only display issues]' \
        '--share[Share the logs using yunopaste]' \
        '--human-readable[Show a human-readable output]' 
}

# (( $+functions[_yunohost_diagnosis_get] )) ||
function _yunohost_diagnosis_get() {
    _arguments -s -C \
        '1:Diagnosis category to fetch results from:__ynh_diagnosis_list' \
        '*:List of criteria describing the test. Must correspond exactly to the '"'"'meta'"'"' infos in '"'"'yunohost diagnosis show'"'"':' 
}

# (( $+functions[_yunohost_diagnosis_run] )) ||
function _yunohost_diagnosis_run() {
    _arguments -s -C \
        '*:Diagnosis categories to run (all by default):__ynh_diagnosis_list' \
        '--force[Ignore the cached report even if it is still '"'"'fresh'"'"']' \
        '--except-if-never-ran-yet[Don'"'"'t run anything if diagnosis never ran yet ... (this is meant to be used by the webadmin)]' \
        '--email[Send an email to root with issues found (this is meant to be used by cron job)]' 
}

# (( $+functions[_yunohost_diagnosis_ignore] )) ||
function _yunohost_diagnosis_ignore() {
    _arguments -s -C \
        '(*)--filter[Add a filter. The first element should be a diagnosis category, and other criterias can be provided using the infos from the '"'"'meta'"'"' sections in '"'"'yunohost diagnosis show'"'"'. For example\: '"'"'dnsrecords domain=yolo.test category=mail'"'"']:*:filter:' \
        '--list[List active ignore filters]' 
}

# (( $+functions[_yunohost_diagnosis_unignore] )) ||
function _yunohost_diagnosis_unignore() {
    _arguments -s -C \
        '(*)--filter[Remove a filter (it should be an existing filter as listed with "ignore --list")]:*:filter:' 
}


#-----------------------------------------
#               storage
#-----------------------------------------

# (( $+functions[_yunohost_storage] )) ||
function _yunohost_storage() {
    if (( CURRENT > 2 )); then
        __jump
    else
        
        local -a yunohost_storage_subcategories; yunohost_storage_subcategories=(
            'disk:Manage et get infos about hard-drives'
        )
        _describe -V -t yunohost-storage-subcategories 'yunohost storage subcategories' yunohost_storage_subcategories "$@"
    fi
}


#-----------------------------------------
#               storage_disk
#-----------------------------------------

# (( $+functions[_yunohost_storage_disk] )) ||
function _yunohost_storage_disk() {
    if (( CURRENT > 2 )); then
        __jump
    else
        local -a yunohost_storage_disk; yunohost_storage_disk=(
            'list:List hard-drives currently attached to this system optionnaly with infos'
            'info:Get hard-drive information'
        )
        _describe -V -t yunohost-storage_disk 'yunohost storage_disk category' yunohost_storage_disk "$@"
        
    fi
}



# (( $+functions[_yunohost_storage_disk_list] )) ||
function _yunohost_storage_disk_list() {
    _arguments -s -C \
        '(-H --human-readable)'{-H,--human-readable}'[Print informations in a human-readable format]' \
        '--human-readable-size[Print sizes in a human-readable format]' \
        '(-i --with-info)'{-i,--with-info}'[Get all informations for each archive]' 
}

# (( $+functions[_yunohost_storage_disk_info] )) ||
function _yunohost_storage_disk_info() {
    _arguments -s -C \
        '(-H --human-readable)'{-H,--human-readable}'[Print informations in a human-readable format]' \
        '--human-readable-size[Print sizes in a human-readable format]' 
}



#-----------------------------------------
#   Completion functions
#-----------------------------------------



# (( $+functions[__ynh_user_list_fields_username] )) ||
function __ynh_user_list_fields_username() {
    compadd "$@" -- ${(@)$(sudo yunohost user list --fields username --output-as json | jq -cr '.users[].username')}
}


# (( $+functions[__ynh_backup_list] )) ||
function __ynh_backup_list() {
    compadd "$@" -- ${(@)$(sudo yunohost backup list --output-as json | jq -cr '.archives[]')}
}


# (( $+functions[__ynh_settings_list] )) ||
function __ynh_settings_list() {
    compadd "$@" -- ${(@)$(sudo yunohost settings list --output-as json | jq -cr '. | keys[]')}
}


# (( $+functions[__ynh_user_group_list] )) ||
function __ynh_user_group_list() {
    compadd "$@" -- ${(@)$(sudo yunohost user group list --output-as json | jq -cr '[(.groups | keys), ([.groups[] | select(.members).members[]] | unique)] | add[]')}
}


# (( $+functions[__ynh_app_catalog] )) ||
function __ynh_app_catalog() {
    compadd "$@" -- ${(@)$(__get_ynh_cache 'YNH_app_catalog' "sudo yunohost app catalog --output-as json | jq -cr '.apps | keys[]'")}
}


# (( $+functions[__ynh_tools_migrations_list] )) ||
function __ynh_tools_migrations_list() {
    compadd "$@" -- ${(@)$(sudo yunohost tools migrations list --output-as json | jq -cr '.migrations[].id')}
}


# (( $+functions[__ynh_log_list] )) ||
function __ynh_log_list() {
    compadd "$@" -- ${(@)$(sudo yunohost log list --output-as json | jq -cr '.operation[].name')}
}


# (( $+functions[__ynh_diagnosis_list] )) ||
function __ynh_diagnosis_list() {
    compadd "$@" -- ${(@)$(sudo yunohost diagnosis list --output-as json | jq -cr '.categories[]')}
}


# (( $+functions[__ynh_user_permission_list] )) ||
function __ynh_user_permission_list() {
    compadd "$@" -- ${(@)$(sudo yunohost user permission list --output-as json | jq -cr '.permissions | keys[]')}
}


# (( $+functions[__ynh_app_list] )) ||
function __ynh_app_list() {
    compadd "$@" -- ${(@)$(sudo yunohost app list --output-as json | jq -cr '.apps[].id')}
}


# (( $+functions[__ynh_user_group_list_s] )) ||
function __ynh_user_group_list_s() {
    compadd "$@" -- ${(@)$(sudo yunohost user group list -s --output-as json | jq -cr '.groups[]')}
}


# (( $+functions[__ynh_service_status] )) ||
function __ynh_service_status() {
    compadd "$@" -- ${(@)$(sudo yunohost service status --output-as json | jq -cr '. | keys[]')}
}


# (( $+functions[__ynh_domain_list] )) ||
function __ynh_domain_list() {
    compadd "$@" -- ${(@)$(sudo yunohost domain list --output-as json | jq -cr '.domains[]')}
}


_yunohost "$@"