#!/usr/bin/bash

# Selected text translator by ibrahim mohammad
# Email: ibrahim.mohammad.2015@gmail.com
# GitHub repository: https://github.com/IbrahimMohammad/st-trans
# No Rights Reserved

help ()
{
    echo -e "st-trans - translate any selected text using Yandex translate.
the command st-trans without any option will send the last selected
text translation as a notification message.

Usage: st-trans [<OPTIONS>|<[SOURCE]:[TARGET]>]

Options:
    -l\t show a list of supported languages and codes.

    -k\t change Yandex Translate API key. write your key after '-k'

    -h\t print this help and exit.

    -t\t specifies the timeout in seconds at which to expire translation
      \t notifications.

    -u\t specifies translator notifications urgency level (low, normal,
      \t critical) in integers (0, 1, 2) respectively.

    -v\t invert source language with target language. note: you can't
      \t use this option when source language set to auto.

      \t run st-trans in instant translation mode, translate selection
    -i\t instantly or when shortcut key pressed. when st-trans already
      \t running in this mode, this option will deactivate instant
      \t translation and translate selection only when shortcut key pressed.

    -a\t auto adjust translation view, with or without hyperlinks
      \t depending on your notification server.

    -d\t use the default rc files. set all options to it's default values.

    -xbk  activate default shortcut keys in xbindkeys.
    
    -no-xbk deactivate default shortcut keys in xbindkeys.
    
Language preferences:
[SOURCE]:[TARGET]
To change source and target language use SOURCE-CODE:TARGET-CODE
For example: to translate from English to French use this command
st-trans en:fr
You can use auto as the source language to auto detect source language
st-trans auto:fr
Also you can change just one language either source by SOURCE: for example:
st-trans en: or target by :TARGET like st-trans :fr

default shortcut keys:
alt+t = st-trans
alt+i = st-trans -i
alt+v = st-trans -v

REPORTING BUGS
https://github.com/IbrahimMohammad/st-trans/issues"
}

adjust_body()
{
    if [[ $1 = start_test ]]; then
        # wait untill Notification server start or a minute passed
        declare -i i=0
        while ! dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply \
            /org/freedesktop/DBus org.freedesktop.DBus.ListNames | grep -qF 'org.freedesktop.Notifications' && [[ $i != 12 ]]; do
            sleep 5
            i+=1
        done
    fi
    # if the current notification server allow hyperlinks
    if dbus-send --session --dest=org.freedesktop.Notifications --type=method_call --print-reply \
        /org/freedesktop/Notifications org.freedesktop.Notifications.GetCapabilities | grep -qF 'hyperlink'; then
        body=\"hyper\"
    else
        body=\"required\"
    fi
}

default_conf()
{
    # installed with
    # .xbindkeysrc
    if [[ $with_xbk = yes ]]; then
        xbk=yes
        xbindkeysrc
    else
        xbk=no
    fi
    # .st-trancrc
    echo "key=\"trnsl.1.1.20151126T100621Z.111380f547c17fd9.6b59d2581e2f22b5baabfdc9f1faa22b8a091198\"
source=\"en\"
target=\"ar\"
urgency=\"normal\"
timeout=\"7000\"
xbk=\"$xbk\"" > $conf
    adjust_body && echo "body="$body"" >> $conf
}

xbindkeysrc()
{
    if ! grep -qF 'st-trans' $xbk_conf &> /dev/null; then
        echo "\"st-trans\"
Alt + t
\"st-trans -i\"
Alt + i
\"st-trans -v\"
Alt + v" >> $xbk_conf && xbindkeys
    fi
}

write_conf()
{
    echo "key=\"$key\"
source=\"$source\"
target=\"$target\"
urgency=\"$urgency\"
timeout=\"$timeout\"
xbk=\"$xbk\"
body=\"$body\"" > $conf
}

translate()
{
    text
    if [[ $source = auto ]]; then
        lang=$target
    else
        lang=$source-$target
    fi
    translation
    required="Powered by Yandex.Translate"
    hyper="Translate on  \<a href\=\"https://translate.google.com/#$source/$target/$send_text\"\>Google\<\/a\>\n\<a href\=\"http://translate.yandex.com/\"\>$required\<\/a\>"
    case $body in
        hyper) body=$hyper
            ;;
        required) body=$required
            ;;
    esac
    # dictionaries
    case $target in
        ar) techdict
            ;;
        *)
            ;;
    esac
    # send notification
    notify-send -u $urgency -t $timeout "$text" "$translation$techdict\n$body"
}

translation()
{
    translation="$(wget -U "Mozilla/5.0" -qO - "https://translate.yandex.net/api/v1.5/tr.json/translate?key=$key&text=$send_text&lang=$lang")"
    translation="$(echo $translation | sed -e 's/.*\[\"//' -e 's/...$//' -e 's/</\&lt\;/g' -e 's/>/\&gt\;/g')"
}

text()
{
    text="$(xsel -o)"
    send_text="$(echo $text | sed -e 's/&/%26/g' -e 's/</%3C/g' -e 's/>/%3E/g' -e 's/#/%23/g' -e 's/+/%2B/g' -e 's/;/%3B/g')"
}

techdict()
{
    # check if tech dictionary exist
    techdict_db=~/.dictdb/techdict.db
    if ! [ -e $techdict_db ]; then
        mkdir -p ~/.dictdb
        wget -qO $techdict_db "https://github.com/IbrahimMohammad/st-trans/blob/master/.dictdb/techdict.db?raw=true"
    fi
    # change first char to uppercase and all chars to lowercase
    tech_text=${text,,}
    tech_text=\'${tech_text^}\'
    # get the translation
    get_tech_translation="$(sqlite3 $techdict_db "select ar,ar1,ar2 from trans where en=$tech_text")"
    tech_translation="$(echo $get_tech_translation | sed -e 's/||//g' -e 's/|$//' -e 's/|/،/')"
    # check if we get a translation
    if ! [ -z $tech_translation ] &> /dev/null; then
        techdict="\nالقاموس التقني: $tech_translation"
    fi
}

notify()
{
    if [[ $1 = error ]]; then
        notify-send -u critical -t 0 'st-trans' "$2"
    else
        notify-send 'st-trans' "$1"
    fi
}

arg_exist()
{
    # ensure that argument exist
    if ! [ -n "$1" ]; then
        help
        exit 1
    fi
}

check_arg()
{
    arg_exist $1
    # check that argument is integer
    if ! [ "$1" -eq "$1" ] &> /dev/null; then
        echo "Sorry, integers only"
        help
        exit 1
    fi
}

# here we go!
conf=~/.st-transrc
xbk_conf=~/.xbindkeysrc
if ! [ -e $conf ]; then
    default_conf
    source $conf
else
    source $conf
    if [ xbk = "yes" ]; then
        xbindkeysrc
    fi
fi

# options
case $1 in
    '') translate
        ;;
    # print languages table
    -l) echo "┌──────────────────────┬───────────────────────┐
│Language Name    Code │Language Name     Code │
│──────────────────────│───────────────────────│
│ Afrikaans      - af  │ Kazakh          - kk  │
│ Albanian       - sq  │ Kirghiz         - ky  │
│ Arabic         - ar  │ Korean          - ko  │
│ Armenian       - hy  │ Latin           - la  │
│ Azerbaijani    - az  │ Latvian         - lv  │
│ Bashkir        - ba  │ Lithuanian      - lt  │
│ Basque         - eu  │ Macedonian      - mk  │
│ Belarusian     - be  │ Malagasy        - mg  │
│ Bosnian        - bs  │ Malay           - ms  │
│ Bulgarian      - bg  │ Maltese         - mt  │
│ Catalan        - ca  │ Mongolian       - mn  │
│ Chinese        - zh  │ Norwegian       - no  │
│ Croatian       - hr  │ Persian         - fa  │
│ Czech          - cs  │ Polish          - pl  │
│ Danish         - da  │ Portuguese      - pt  │
│ Dutch          - nl  │ Romanian        - ro  │
│ English        - en  │ Russian         - ru  │
│ Estonian       - et  │ Serbian         - sr  │
│ Finnish        - fi  │ Slovak          - sk  │
│ French         - fr  │ Slovenian       - sl  │
│ Galician       - gl  │ Spanish         - es  │
│ Georgian       - ka  │ Swahili         - sw  │
│ German         - de  │ Swedish         - sv  │
│ Greek          - el  │ Tagalog         - tl  │
│ Haitian        - ht  │ Tajik           - tg  │
│ Hebrew         - he  │ Tatar           - tt  │
│ Hungarian      - hu  │ Thai            - th  │
│ Icelandic      - is  │ Turkish         - tr  │
│ Indonesian     - id  │ Ukrainian       - uk  │
│ Irish          - ga  │ Uzbek           - uz  │
│ Italian        - it  │ Vietnamese      - vi  │
│ Japanese       - ja  │ Welsh           - cy  │
└──────────────────────┴───────────────────────┘"
        ;;
    # auto adjust translation view
    -a) if [[ $2 = start_test ]]; then
            adjust_body start_test
        else
            adjust_body
        fi && write_conf
        ;;
    # change languages
    *:*) new_source="$(echo "$1" | cut -sd ':' -f 1)"
         new_target="$(echo "$1" | cut -sd ':' -f 2)"
         # is there are a source language?
         if [ -n "$new_source" ]; then
             # check language code
             if ! grep -q "\- $new_source " /usr/bin/st-trans  &&  [ "$new_source" != "auto" ]; then
                     echo "\"$new_source\" isn't a supported language code. please take a look at languages table with st-trans -l"
                     exit 1
             fi
             # change source language
             source=$new_source
             write_conf
         fi
         # is there are a target language?
         if [ -n "$new_target" ]; then
             # check language code
             if ! grep -q "\- $new_target " /usr/bin/st-trans; then
                 echo "\"$new_target\" isn't a supported language code. please take a look at supported languages table with st-trans -l"
                 exit 1
             fi
             # change target language
             target=$new_target
             write_conf
         fi
         ;;
    # change API key
    -k) arg_exist $2
        if [[ $2 = trns* ]]; then
            key=$2
            write_conf
        else
            echo "Sorry, wrong API key"
            exit 1
        fi
        ;;
    # invert source language with target language
    -v) if [[ $source = auto ]]; then
            notify error "Sorry, source language is set as auto so you can't invert it.\nPlease change source language to any supported language to be able to invert it with the target language."
            exit 1
        fi
        # invert
        temp=$source
        source=$target
        target=$temp
        write_conf
        notify "languages inverted"
        ;;
    # change timeout period
    -t) check_arg $2
        timeout=$(($2*1000))
        write_conf
        ;;
    # change urgency level:
    -u) check_arg $2
        case $2 in
            0)  urgency=low
                ;;
            1)  urgency=normal
                ;;
            2)  urgency=critical
                ;;
            *)  echo "invalid number."
                help
                exit 1
                ;;
        esac
        write_conf
        ;;
    # instant translation mode
    -i) # if the daemon already running close it if not run it
        if killall st-trans-daemon &> /dev/null; then
            notify 'Instant translation mode deactivated.'
        else
            setsid st-trans-daemon < /dev/null &> /dev/null&
            notify 'Instant translation mode activated.'
        fi
        ;;
    -d) default_conf
        ;;
    -h|--help|help) help
                    ;;
    # activate xbindkeys shortcut keys.
    -xbk) xbindkeysrc
          xbk=yes
          write_conf
          ;;
    # deactivate xbindkeys shortcut keys.
    -no-xbk) sed -i '/"st-trans/{n;d}' $xbk_conf
             sed -i '/"st-trans/d' $xbk_conf
             killall -HUP xbindkeys &> /dev/null
             xbk=no
             write_conf
             ;;
    # more options here
    *) help
       exit 1
       ;;
esac
