#compdef gmtool
#
# completion definition for gmtool
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#      http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.
#
_gmtool_prepare_command_list() {
    # Expects to be called with `current_cmd cmd1 cmd2 cmd3...`
    # Prints a string suitable for _values
    # For example:
    #   foo foo bar baz => "(bar baz)foo"
    #   bar foo bar baz => "(foo baz)bar"
    local all_cmds other_cmds cmd current_cmd
    current_cmd=$1
    shift
    other_cmds=()
    for cmd in $* ; do
        if [ "$cmd" != "$current_cmd" ] ; then
            other_cmds+="$cmd"
        fi
    done
    echo "($other_cmds)$current_cmd"
}

_gmtool() {
    # must be set when using the :-> syntax in _arguments
    local context state state_descr line
    typeset -A opt_args

    _arguments : \
        {-t,--timeout}'[Set a timeout]:timeout:' \
        {-v,--verbose}'[Be verbose]' \
        ': :->command' \
        '*:: :->option-or-argument'

    case $state in
        (command)
            _gmtool_cmd_main
            ;;
        (option-or-argument)
            # this means that we have the words and CURRENT variable set correctly
            cmd=${words[1]}
            if [[ $cmd != "version" ]]; then
                _gmtool_cmd_$cmd
            fi
            ;;
    esac
}

_gmtool_cmd_main() {
    local main_cmds
    main_cmds=(config admin device version help license)
    _values "Command group" \
        "$(_gmtool_prepare_command_list license $main_cmds)[license operations]" \
        "$(_gmtool_prepare_command_list config $main_cmds)[configuration operations]" \
        "$(_gmtool_prepare_command_list admin $main_cmds)[administration operations]" \
        "$(_gmtool_prepare_command_list device $main_cmds)[device operations]" \
        "$(_gmtool_prepare_command_list version $main_cmds)[version]" \
        "$(_gmtool_prepare_command_list help $main_cmds)[help]"
}

_gmtool_cmd_help() {
    if (( CURRENT > 2)); then
        local cmd=${words[2]};
        # set the context (zstyle)
        curcontext="${curcontext%:*:*}:gmtool-$cmd"
        (( CURRENT-- ))
        shift words
        if [[ $cmd != "version" && $cmd != "help" ]]; then
            _gmtool_cmd_help_$cmd
        fi
    else
        _gmtool_cmd_help_main
    fi
}

_gmtool_cmd_help_main() {
    local main_cmds
    main_cmds=(config admin device version help license)
    _values "Command group" \
        "$(_gmtool_prepare_command_list license $main_cmds)[license operations]" \
        "$(_gmtool_prepare_command_list config $main_cmds)[configuration operations]" \
        "$(_gmtool_prepare_command_list admin $main_cmds)[administration operations]" \
        "$(_gmtool_prepare_command_list device $main_cmds)[device operations]" \
        "$(_gmtool_prepare_command_list version $main_cmds)[version]" \
        "$(_gmtool_prepare_command_list help $main_cmds)[help]"
}

_gmtool_cmd_help_admin() {
    local admin_cmds
    admin_cmds=(list logzip start stop stopall delete details clone templates factoryreset create edit)
    _values -w "Administration commands" \
        "$(_gmtool_prepare_command_list logzip $admin_cmds)[Generate an archive of all Genymotion log files]" \
        "$(_gmtool_prepare_command_list list $admin_cmds)[List all virtual devices]" \
        "$(_gmtool_prepare_command_list start $admin_cmds)[Start a virtual device]" \
        "$(_gmtool_prepare_command_list stop $admin_cmds)[Stop a virtual device]" \
        "$(_gmtool_prepare_command_list stopall $admin_cmds)[Stop all virtual devices]" \
        "$(_gmtool_prepare_command_list delete $admin_cmds)[Delete a virtual device]" \
        "$(_gmtool_prepare_command_list details $admin_cmds)[Get virtual device's properties]" \
        "$(_gmtool_prepare_command_list clone $admin_cmds)[Clone a virtual device]" \
        "$(_gmtool_prepare_command_list templates $admin_cmds)[List the available virtual device templates]" \
        "$(_gmtool_prepare_command_list factoryreset $admin_cmds)[Restore a virtual device to factory state]" \
        "$(_gmtool_prepare_command_list create $admin_cmds)[Create a virtual device]" \
        "$(_gmtool_prepare_command_list edit $admin_cmds)[Edit a virtual device]"
}

_gmtool_cmd_help_license() {
    local all_cmds
    all_cmds=(register count validity info)
    _values -w "License commands" \
        "$(_gmtool_prepare_command_list info $all_cmds)[get license informations]" \
        "$(_gmtool_prepare_command_list register $all_cmds)[register license]" \
        "$(_gmtool_prepare_command_list count $all_cmds)[get activated workstations]" \
        "$(_gmtool_prepare_command_list validity $all_cmds)[get number of active days left]"
}

_gmtool_cmd_help_config() {
    local all_cmds
    all_cmds=(print clearcache username password license_server license_server_address statistics virtual_device_path sdk_path use_custom_sdk screen_capture_path proxy proxy_address proxy_port proxy_auth proxy_username proxy_password reset trusted_hosts)
    _values -w "configuration parameters" \
        "$(_gmtool_prepare_command_list reset $all_cmds)[Reset the configuration]" \
        "$(_gmtool_prepare_command_list print $all_cmds)[Print the configuration]" \
        "$(_gmtool_prepare_command_list clearcache $all_cmds)[Remove temporary and downloaded files]"
}

_gmtool_cmd_help_device() {
    _values "Device commands" \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)logcatdump[Dump logcat]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)logcatclear[Clear logcat]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)push[Push a file]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)pull[Pull a file]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)install[Install an application]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)flash[Flash an archive]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)adbdisconnect[Disconnect adb]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)adbconnect[Connect adb]'
}

_gmtool_cmd_license() {
    if (( CURRENT > 2)); then
        local cmd=${words[2]};
        # set the context (zstyle)
        curcontext="${curcontext%:*:*}:gmtool-license-$cmd"
        (( CURRENT-- ))
        shift words

        case $cmd in
        register)
            _gmtool_cmd_license_register
            ;;
        esac
    else
        local all_cmds
        all_cmds=(register count validity info)
        _values "License commands" \
            "$(_gmtool_prepare_command_list info $all_cmds)[get license informations]" \
            "$(_gmtool_prepare_command_list register $all_cmds)[register license]" \
            "$(_gmtool_prepare_command_list count $all_cmds)[get activated workstations]" \
            "$(_gmtool_prepare_command_list validity $all_cmds)[get number of active days left]"
    fi
}

_gmtool_cmd_license_register() {
    _arguments : \
        ':license number: '
}

_gmtool_cmd_admin() {
    local admin_cmds
    admin_cmds=(list logzip start stop stopall delete details clone templates factoryreset create edit)
    if (( CURRENT > 2)); then
        local cmd=${words[2]};
        # set the context (zstyle)
        curcontext="${curcontext%:*:*}:gmtool-admin-$cmd"
        (( CURRENT-- ))
        shift words

        if [[ $cmd != "stopall" ]]; then
            _gmtool_cmd_admin_$cmd
        fi
    else
        echo $out > /tmp/zog 2>&1
        _values "Administration commands" \
            "$(_gmtool_prepare_command_list logzip $admin_cmds)[Generate an archive of all Genymotion log files]" \
            "$(_gmtool_prepare_command_list list $admin_cmds)[List all virtual devices]" \
            "$(_gmtool_prepare_command_list start $admin_cmds)[Start a virtual device]" \
            "$(_gmtool_prepare_command_list stop $admin_cmds)[Stop a virtual device]" \
            "$(_gmtool_prepare_command_list stopall $admin_cmds)[Stop all virtual devices]" \
            "$(_gmtool_prepare_command_list delete $admin_cmds)[Delete a virtual device]" \
            "$(_gmtool_prepare_command_list details $admin_cmds)[Get virtual device's properties]" \
            "$(_gmtool_prepare_command_list clone $admin_cmds)[Clone a virtual device]" \
            "$(_gmtool_prepare_command_list templates $admin_cmds)[List the available virtual device templates]" \
            "$(_gmtool_prepare_command_list factoryreset $admin_cmds)[Restore a virtual device to factory state]" \
            "$(_gmtool_prepare_command_list create $admin_cmds)[Create a virtual device]" \
            "$(_gmtool_prepare_command_list edit $admin_cmds)[Edit a virtual device]"
    fi
}

_gmtool_cmd_admin_logzip() {
    _arguments : \
        {-n,--name}'[Virtual device]:Virtual device:_gmtool_cmd_admin_add_device_name' \
        ':log archive path:_files -/'
}

_gmtool_cmd_admin_list() {
    _arguments : \
        - set1 \
        '--running[List only running devices]' \
        - set2 \
        '--off[List only powered-off devices]'
}

_gmtool_cmd_admin_start() {
    _gmtool_cmd_admin_add_device_name --off
}

_gmtool_cmd_admin_stop() {
    _gmtool_cmd_admin_add_device_name --running
}

_gmtool_cmd_admin_delete() {
    _gmtool_cmd_admin_add_device_name
}

_gmtool_cmd_admin_factoryreset() {
    _gmtool_cmd_admin_add_device_name
}

_gmtool_cmd_admin_details() {
    _arguments : \
        '*:virtual device:_gmtool_cmd_admin_add_device_name'
}

_gmtool_cmd_admin_clone() {
    _arguments : \
        '1:original virtual device:_gmtool_cmd_admin_add_device_name' \
        ':new virtual device: '
}

_gmtool_cmd_admin_templates() {
    _arguments : \
        '(-f --force-refresh)'{-f,--force-refresh}'[force refresh]' \
        '--full[display all properties]'
}

_gmtool_cmd_admin_create() {
    _arguments : \
        '--density[screen density]:screen density:' \
        '--width[screen width]:screen width:' \
        '--height[screen height]:screen height:' \
        '--nbcpu[number of cpus]:number of cpus:' \
        '--ram[RAM in MB]:RAM in MB:' \
        '--navbar[navigation bar]:navigation bar:(on off)' \
        '--virtualkeyboard[virtual keyboard]:virtual keyboard:(on off)' \
        '--network-mode[network mode]:network mode:(nat bridge)' \
        '--bridged-if[bridged interface]:bridged interface:_net_interfaces' \
        '*--sysprop[system property]:system property:_gmtool_sysprop' \
        '1:template:_gmtool_cmd_admin_add_template_name' \
        ':new virtual device: '
}

_gmtool_cmd_admin_edit() {
    _arguments : \
        '--density[screen density]:screen density:' \
        '--width[screen width]:screen width:' \
        '--height[screen height]:screen height:' \
        '--nbcpu[number of cpus]:number of cpus:' \
        '--ram[RAM in MB]:RAM in MB:' \
        '--navbar[navigation bar]:navigation bar:(on off)' \
        '--virtualkeyboard[virtual keyboard]:virtual keyboard:(on off)' \
        '--network-mode[network mode]:network mode:(nat bridge)' \
        '--bridged-if[bridged interface]:bridged interface:_net_interfaces' \
        '*--sysprop[system property]:system property:_gmtool_sysprop' \
        '1:virtual device:_gmtool_cmd_admin_add_device_name'
}

_gmtool_sysprop() {
    local sysprops
    sysprops=(PRODUCT MODEL MANUFACTURER BRAND BOARD DISPLAY DEVICE \
              SERIAL TYPE FINGERPRINT TAGS)
    compadd -S: $sysprops[@]
}

_gmtool_filter_genymotion_vm() {
    # Expects vmname in stdin, prints vmname on stdout if it is a Genymotion VM
    local out
    while read vmname ; do
        out=$(vboxmanage guestproperty get "$vmname" vbox_graph_mode)
        if [ "$out" != 'No value set!' ] ; then
            echo $vmname
        fi
    done
}

_gmtool_cmd_admin_add_device_name() {
    local devices
    devices=(${(f)"$(vboxmanage list vms | awk -F"\"" '{print $2}' | _gmtool_filter_genymotion_vm)"})

    if [[ $#devices -gt 0 ]] ; then
        compadd $devices[@]
        return 0
    fi
    return 1
}

_gmtool_cmd_admin_add_template_name() {
    local lines
    local -a templates
    lines=(${(f)"$(gmtool admin templates 2>/dev/null)"})
    for line in $lines; do
        [[ $line =~ "Name: *" ]] && templates+=${line#Name: }
    done

    if [[ $#templates -gt 0 ]] ; then
        compadd $templates[@]
        return 0
    fi
    return 1
}

_gmtool_cmd_device() {
    _arguments : \
        '(-n --name)'{-n,--name}'[virtual device name]:virtual device name:_gmtool_cmd_admin_add_device_name' \
        '--all[All virtual devices]' \
        '--start[Started virtual devices]' \
        '(-): :->command' \
        '(-)*:: :->option-or-argument' && return

    case $state in
    (command)
        _gmtool_cmd_device_commands && return 0
        ;;
    (option-or-argument)
        local cmd
        cmd=$words[1]
        curcontext=${curcontext%:*:*}:gmtool-device-$cmd

        if [[ $cmd != "logcatclear" &&
                $cmd != "adbdisconnect" ]]; then
            _gmtool_cmd_device_$cmd
        fi
        ;;

    esac
    return 0
}

_gmtool_cmd_device_commands() {
    _values "Device commands" \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)logcatdump[Dump logcat]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)logcatclear[Clear logcat]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)push[Push a file]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)pull[Pull a file]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)install[Install an application]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)flash[Flash an archive]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)adbdisconnect[Disconnect adb]' \
        '(logcatdump logcatclear push pull install flash adbdisconnect adbconnect)adbconnect[Connect adb]'
}

_gmtool_cmd_device_logcatdump() {
    _arguments : \
        ':destination file path:_files'
}

_gmtool_cmd_device_push() {
    _arguments : \
        '1:source file:_files' \
        '::destination file: '
}

_gmtool_cmd_device_pull() {
    _arguments : \
        '1:source file: ' \
        '::destination file:_files'
}

_gmtool_cmd_device_install() {
    _arguments : \
        ':android application file:_files -g "*.apk"'
}

_gmtool_cmd_device_flash() {
    _arguments : \
        ':android flash zip file:_files -g "*.zip"'
}

_gmtool_cmd_config() {
    local all_cmds
    all_cmds=(print clearcache username password license_server license_server_address statistics virtual_device_path sdk_path use_custom_sdk screen_capture_path proxy proxy_address proxy_port proxy_auth proxy_username proxy_password reset trusted_hosts)

    _values -w "configuration parameters" \
        '(reset print clearcache)username[Username]:Username:' \
        '(reset print clearcache)password[Password]:Password:' \
        '(reset print clearcache)license_server[Use license server]:(on off)' \
        '(reset print clearcache)license_server_address[License server address]:License server address:' \
        '(reset print clearcache)statistics[statistics]:Send statistics:(on off)' \
        '(reset print clearcache)virtual_device_path[Path for virtual devices]:Path for virtual devices:_files' \
        '(reset print clearcache)sdk_path[Path for Android SDK]:Path for Android SDK:_files' \
        '(reset print clearcache)use_custom_sdk[Use custom Android SDK]:Use custom Android SDK:(on off)' \
        '(reset print clearcache)screen_capture_path[Path for screen capture]:Path for screen capture:_files' \
        '(reset print clearcache)proxy[Use a proxy]:Use a proxy:(on off)' \
        '(reset print clearcache)proxy_address[Address of the proxy]:Address of the proxy:' \
        '(reset print clearcache)proxy_port[Port of the proxy]:Port of the proxy:' \
        '(reset print clearcache)proxy_auth[Authenticate to the proxy]:Authenticate to the proxy:(on off)' \
        '(reset print clearcache)proxy_username[Proxy username]:Proxy username:' \
        '(reset print clearcache)proxy_password[Proxy password]:Proxy password:' \
        '(reset print clearcache)trusted_hosts[Trusted hosts]:Trusted hosts:' \
        "$(_gmtool_prepare_command_list reset $all_cmds)[Reset the configuration]" \
        "$(_gmtool_prepare_command_list print $all_cmds)[Print the configuration]" \
        "$(_gmtool_prepare_command_list clearcache $all_cmds)[Remove temporary and downloaded files]"
}

_gmtool "$@"
