#!/bin/bash

# setup #######################################################################
#set -o errexit -o pipefail -o noclobber -o nounset
LANGUAGE="${DEEPL_TARGET:-EN}"
LANGUAGE_SOURCE="${DEEPL_SOURCE:-auto}"
LANGUAGE_PREFERRED="${DEEPL_PREFERRED:-[\"DE\",\"EN\"]}"
KEY="${DEEPL_KEY:-}"
PRO="${DEEPL_PRO:-}"
# see https://developers.deepl.com/docs/api-reference/translate/openapi-spec-for-text-translation
FORMALITY="${DEEPL_FORMALITY:-prefer_less}"
POSTFIX="${DEEPL_POSTFIX:-.}"
VERSION="2.1.0"
PATH="$PATH:/usr/local/bin/"
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" >/dev/null 2>&1 && pwd )"
###############################################################################

# helper functions ############################################################
function printJson() {
  echo '{"items": [{"uid": null,"arg": "'"$1"'","valid": "yes","autocomplete": "autocomplete","title": "'"$1"'"}]}'
}
###############################################################################

# parameters ##################################################################
POSITIONAL=()
while [[ $# -gt 0 ]]; do
  key="$1"
  case "$key" in
  -l | --lang)
    LANGUAGE="$2"
    shift # past argument
    shift # past value
    ;;
  *) # unknown option
    POSITIONAL+=("$1") # save it in an array for later
    shift              # past argument
    ;;
  esac
done
set -- "${POSITIONAL[@]:-}" # restore positional parameters
###############################################################################

# help ########################################################################
if [ -z "$1" ]; then
  echo "Home made DeepL CLI (${VERSION}; https://github.com/AlexanderWillner/deepl-alfred-workflow2)"
  echo ""
  echo "SYNTAX : $0 [-l language] <query>" >&2
  echo "Example: $0 -l DE \"This is just an example.\""
  echo ""
  exit 1
fi
###############################################################################

# process query ###############################################################
query="$1"
# shellcheck disable=SC2001
query="$(echo "$query" | sed 's/\"/\\\"/g')"
# shellcheck disable=SC2001
query="$(echo "$query" | sed "s/'/\\\'/g")"
query="$(echo "$query" | iconv -f utf-8-mac -t utf-8 | xargs)"

if [[ $KEY = "" ]] && [[ $query != *"$POSTFIX"   ]]; then
  printJson "End query with $POSTFIX"
  exit 2
fi
###############################################################################

# prepare query ###############################################################
# shellcheck disable=SC2001
query="$(echo "$query" | sed "s/\\$POSTFIX$//")"
if [ "$KEY" = "" ]; then
  FORM_PARAM=''
else
  FORM_PARAM='"formality": "'"$FORMALITY"'", '
fi
data='{"jsonrpc":"2.0","method": "LMT_handle_jobs","params":{"commonJobParams": {'$FORM_PARAM'"browserType": 1, "mode": "translate", "textType": "plaintext"}, "jobs":[{"kind":"default","raw_en_sentence":"'"$query"'","preferred_num_beams":4,"raw_en_context_before":[],"raw_en_context_after":[],"quality":"fast"}],"lang":{"user_preferred_langs":'"${LANGUAGE_PREFERRED}"',"source_lang_user_selected":"'"${LANGUAGE_SOURCE}"'","target_lang":"'"${LANGUAGE:-EN}"'"},"priority":1,"timestamp":1557063997314},"id":79120002}'
HEADER=(
  --compressed
  -H 'authority: www2.deepl.com'
  -H 'Origin: https://www.deepl.com'
  -H 'Referer: https://www.deepl.com/translator'
  -H 'Accept: */*'
  -H 'Content-Type: application/json'
  -H 'Accept-Language: en-us'
  -H 'User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_4) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.1 Safari/605.1.15'
)
###############################################################################

# query #######################################################################
if [ -n "$KEY" ]; then
  if [ "$PRO" = "1" ]; then
    url="https://api.deepl.com/v2/translate"
  else
    url="https://api-free.deepl.com/v2/translate"
  fi
  if [ ! -z "$DEEPL_HOST" ]; then
    url="$DEEPL_HOST/v2/translate"
  fi

  echo >&2 "curl -s -X POST '$url' -H 'Authorization: DeepL-Auth-Key $KEY' --data-urlencode 'text=$query' -d 'formality=$FORMALITY' -d 'target_lang=${LANGUAGE:-EN}'"
  result=$(curl -s -X POST "$url" -H "Authorization: DeepL-Auth-Key $KEY" --data-urlencode "text=$query" -d "formality=$FORMALITY" -d "target_lang=${LANGUAGE:-EN}")
  ret=$?
  if [[ "x$ret" != "x0" ]] || [[ "$result" == "" ]]; then
    echo >&2 "$ret: $result"
    http_code=$(curl -s -X POST "$url" -H "Authorization: DeepL-Auth-Key $KEY" --data-urlencode "text=$query" -d "target_lang=${LANGUAGE:-EN}" -d "formality=$FORMALITY" -w %{http_code} -o /dev/null)
    if [[ $http_code -eq 403 ]]; then
      printJson "Error: Invalid API key"
      exit 3
    fi
    if [[ $ret -eq 6 ]]; then
      printJson "Error: DNS resolution failed - no Internet connection?"
      exit 4
    fi
    printJson "Error Code $ret - HTTP Code $http_code"
    exit 5
  fi
  osascript -l JavaScript -e 'function run(argv) {
    try {
      const parsed = JSON.parse(argv[0]);
      if (!parsed || !parsed.translations) {
        throw new Error("Invalid response structure");
      }
      const translations = parsed.translations.map(item => ({
        title: item["text"],
        arg: item["text"]
      }));
      return JSON.stringify({ items: translations }, null, 2);
    } catch(e) {
      return JSON.stringify({ 
        items: [{ 
          title: "Error parsing response: " + e.message, 
          arg: "error",
          valid: false 
        }] 
      }, null, 2);
    }
  }' "$result" || {
    echo >&2 "ERROR w/ key: result '$result', query '$query'"
    printJson "Error: Failed to parse translation response"
    exit 10
  }
else
  echo >&2 "curl -s 'https://www2.deepl.com/jsonrpc' '${HEADER[@]}' --data-binary $'$data'"
  result=$(curl -s 'https://www2.deepl.com/jsonrpc' "${HEADER[@]}" --data-binary $"$data")
  ret=$?
  echo >&2 "DEBUG: curl exit code: $ret"
  echo >&2 "DEBUG: result length: ${#result}"
  echo >&2 "DEBUG: result first 200 chars: ${result:0:200}"
  
  if [[ "x$ret" != "x0" ]] || [[ "$result" == "" ]]; then
    echo >&2 "$ret: $result"
    http_code=$(curl -s 'https://www2.deepl.com/jsonrpc' "${HEADER[@]}" --data-binary $"$data" -w %{http_code} -o /dev/null)
    if [[ $ret -eq 6 ]]; then
      printJson "Error: DNS resolution failed - no Internet connection?"
      exit 6
    fi
    printJson "Error Code $ret - HTTP Code $http_code"
    exit 7
  fi
  # Validate JSON before parsing
  if ! echo "$result" | python3 -m json.tool > /dev/null 2>&1; then
    echo >&2 "ERROR: Invalid JSON response: $result"
    printJson "Error: Invalid JSON response from DeepL"
    exit 8
  fi
  
  if [[ $result == *'"error":{"code":'* ]]; then
    message="$(osascript -l JavaScript -e 'function run(argv) { 
      try {
        return JSON.parse(argv[0])["error"]["message"] 
      } catch(e) {
        return "JSON parse error: " + e.message
      }
    }' "$result")"
    printJson "Error: $message"
    exit 8
  else
    osascript -l JavaScript -e 'function run(argv) {
      try {
        const parsed = JSON.parse(argv[0]);
        if (!parsed || !parsed.result || !parsed.result.translations || !parsed.result.translations[0] || !parsed.result.translations[0].beams) {
          throw new Error("Invalid response structure");
        }
        const translations = parsed.result.translations[0].beams.map(item => ({
          title: item["postprocessed_sentence"],
          arg: item["postprocessed_sentence"]
        }));
        return JSON.stringify({ items: translations }, null, 2);
      } catch(e) {
        return JSON.stringify({ 
          items: [{ 
            title: "Error parsing response: " + e.message, 
            arg: "error",
            valid: false 
          }] 
        }, null, 2);
      }
    }' "$result" || {
      echo >&2 "ERROR w/o key: result '$result', query '$query'"
      printJson "Error: Failed to parse translation response"
      exit 9
    }
  fi
fi
###############################################################################
