#compdef aptible

_aptible() {
    _arguments \
        '1: :_aptible_cmds' \
        '*:: :->args'

    local -a sizes; sizes=(512 1024 2048 4096 8192 16384 32768 65536);
    case $state in
        args)
            case $words[1] in
                help)
                    _arguments \
                        '*: :_aptible_cmds'
                    ;;
                apps|db:list)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs'
                    ;;
                apps:create)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs'
                    ;;
                apps:deprovision|config*|ps|rebuild)
                    _arguments \
                        '--app=[APP]: :_aptible_apps' \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '(-r, --remote)'{-r,--remote}'[REMOTE]'
                    ;;
                apps:scale)
                    _arguments \
                        '--app=[APP]: :_aptible_apps' \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '(-r, --remote)'{-r,--remote}'[REMOTE]' \
                        '--size=[N]: :{_describe "N" sizes}'
                    ;;
                backup:list)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '--max-age=[MAX_AGE]' \
                        ':: :_aptible_dbs'
                    ;;
                backup:restore)
                    _arguments \
                        '--handle=[HANDLE]: :_aptible_dbs' \
                        '--size=[N]: :{_describe "N" sizes}'
                    ;;
                db:backup|db:clone|db:deprovision|db:dump)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        ':: :_aptible_dbs'
                    ;;
                db:create)
                    _arguments \
                        '--type=[TYPE, Default\: postgresql]' \
                        '--size=[N, Default\: 10]' \
                        '--environment=[ENVIRONMENT]: :_aptible_envs'
                    ;;
                db:execute)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '1: :_aptible_dbs' \
                        '2: :_files'
                    ;;
                db:tunnel)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '--port=[N]' \
                        ':: :_aptible_dbs'
                    ;;
                domains)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '--app=[APP]: :_aptible_apps' \
                        '(-r, --remote)'{-r,--remote}'[REMOTE]' \
                        '(-v, --verbose)'{-v,--verbose}'[VERBOSE]'
                    ;;
                login)
                    _arguments \
                        '--email=[EMAIL]' \
                        '--password=[PASSWORD]' \
                        '--lifetime=[LIFETIME, e.g. 24h, 1d, 600s, etc]' \
                        '--otp-token=[OTP_TOKEN, A token generated by your second-factor app]'
                    ;;
                logs)
                    _arguments \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '--app=[APP]: :_aptible_apps' \
                        '(-r, --remote)'{-r,--remote}'[REMOTE]' \
                        '--database=[DATABASE]: :_aptible_dbs'
                    ;;
                restart)
                    _arguments \
                        "--simulate-oom=[Add this flag to simulate an OOM restart and test your app's response (not recommended on production apps)]" \
                        "--force[Add this flag to use --simulate-oom in a production environment, which is not allowed by default]" \
                        '--app=[APP]: :_aptible_apps' \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '(-r, --remote)'{-r,--remote}'[REMOTE]'
                    ;;
                ssh)
                    _arguments \
                        '--app=[APP]: :_aptible_apps' \
                        '--environment=[ENVIRONMENT]: :_aptible_envs' \
                        '(-r, --remote)'{-r,--remote}'[REMOTE]' \
                        '--force-tty' \
                        '--force-no-tty'
                    ;;
            esac
            ;;
    esac
}

_aptible_dbs() {
    if [ -f "/tmp/aptible_dbs_zsh_cache" ]; then
        local cache_time=$(stat -c %Y "/tmp/aptible_dbs_zsh_cache")
        local expiration=$(date -d "now - 1 day" +%s)
        if [ $cache_time -gt $expiration ]; then
            local dbs; dbs=(
            $(cat "/tmp/aptible_dbs_zsh_cache")
            );
            _describe 'db' dbs
        else
            _fetch_aptible_dbs
        fi
    else
        _fetch_aptible_dbs
    fi
}

_fetch_aptible_dbs() {
    aptible db:list | egrep -v "^=" > /tmp/aptible_dbs_zsh_cache
    _aptible_dbs
}

_aptible_apps() {
    if [ -f "/tmp/aptible_apps_zsh_cache" ]; then
        local cache_time=$(stat -c %Y "/tmp/aptible_apps_zsh_cache")
        local expiration=$(date -d "now - 1 day" +%s)
        if [ $cache_time -gt $expiration ]; then
            local apps; apps=(
            $(cat "/tmp/aptible_apps_zsh_cache")
            );
            _describe 'app' apps
        else
            _fetch_aptible _aptible_apps
        fi
    else
        _fetch_aptible _aptible_apps
    fi
}

_fetch_aptible() {
    local list=$(aptible apps)
    echo $list | egrep -v "^=" > /tmp/aptible_apps_zsh_cache
    echo $list | egrep "^=" | tr -d '=' > /tmp/aptible_envs_zsh_cache
    $1
}

_aptible_envs() {
    if [ -f "/tmp/aptible_envs_zsh_cache" ]; then
        local cache_time=$(stat -c %Y "/tmp/aptible_envs_zsh_cache")
        local expiration=$(date -d "now - 1 day" +%s)
        if [ $cache_time -gt $expiration ]; then
            local apps; apps=(
            $(cat "/tmp/aptible_envs_zsh_cache")
            );
            _describe 'app' apps
        else
            _fetch_aptible _aptible_envs
        fi
    else
        _fetch_aptible _aptible_envs
    fi
}

_aptible_cmds() {
    local -a commands; commands=(
    "apps:List all applications"
    "apps\:create:Create a new application"
    "apps\:deprovision:Deprovision an app"
    "apps\:scale:Scale app to NUMBER of instances"
    "backup\:list:List backups for a database"
    "backup\:restore:Restore a backup"
    "config:Print an app's current configuration"
    "config\:add:Add an ENV variable to an app"
    "config\:rm:Remove an ENV variable from an app"
    "config\:set:Alias for config:add"
    "config\:unset:Alias for config:rm"
    "db\:backup:Backup a database"
    "db\:clone:Clone a database to create a new one"
    "db\:create:Create a new database"
    "db\:deprovision:Deprovision a database"
    "db\:dump:Dump a remote database to file"
    "db\:execute:Executes sql against a database"
    "db\:list:List all databases"
    "db\:tunnel:Create a local tunnel to a database"
    "domains:Print an app's current virtual domains"
    "help:Describe available commands or one specific command"
    "login:Log in to Aptible"
    "logs:Follows logs from a running app or database"
    "operation\:cancel:Cancel a running operation"
    "ps:Display running processes for an app - DEPRECATED"
    "rebuild:Rebuild an app, and restart its services"
    "restart:Restart all services associated with an app"
    "ssh:Run a command against an app"
    "version:Print Aptible CLI version"
    );

    _describe 'command' commands
}

_aptible
