#!/bin/bash


# helper python command to unescape html entities
dev::xml_unescape() {

local py_script="
import sys, HTMLParser
parser = HTMLParser.HTMLParser()
print parser.unescape(sys.argv[1])
"
python -c "$py_script" $1
}

dev::description() {
    echo "Syndesis developer tools"
}

dev::usage() {
    cat <<"EOF"
    --bump-camel <version>    Bump the camel version to the one specified
    --cleanup                 Removes 'Completed' pods
    --cleanup --nuke          Remove all Syndesis created OpenShift objects and remove all data from the database
    --cookie                  Loads a local valid cookie to access Syndesis APIs when using Minishift
                              (both switches need to be specified)
    --debug <name>            Setup a port forwarding to <name> pod (default: server)
    --install-maven-mirror    Install Maven Nexus app as mirror to current cluster.
    --refresh                 Used in conjuction with --cookie, forces a refresh of the cookie.
                              Ex: curl -k --cookie $(syndesis dev --cookie --refresh)  "https://$(oc get route syndesis  --template={{.spec.host}})/api/v1/connections"
    --update-manifest <name>  Updates the json manifest for the given connector
    --version                 Show running version of cluster
EOF
}

extract_and_escape() {
    local variable=$(grep  -E name=\"$1\" $2 | grep -Po '(?<=value=")[^"]+' )
    variable="$(dev::xml_unescape $variable)"
    echo "$variable"
}

create_api_cookie() {
    local cookie_cached=$1

    # second cookie needed because curl flushes old values upon redirect. Might be a bug or some obscure flag missing
    local cookie_new="$(mktemp /tmp/syndesis_cookie.XXX.txt)"
    # generate a new user so that it will be asked to approve permissions delegation
    local username="dev$RANDOM"

    # clean cookie
    [ -f $cookie_cached ] && rm -rf "$cookie_cached"
    touch "$cookie_cached"

    local syndesis_url="$(oc get route syndesis  --template={{.spec.host}})"
    local openshift_ip_and_port="$(oc status | grep "In project" | grep  -Po --color=never '(?<=server https://).*' )"
    # first invocation is needed just to get the redierect url and to define a csrf token
    local redirect_url="$(curl --write-out "%{url_effective}\n" --location --silent --show-error --output /dev/null --insecure --cookie-jar  "$cookie_cached" -v "https://$syndesis_url" 2>/dev/null )"

    # isolate required params
    # split on question mark, so we are sure the first part is always the correct url
    local login_url="$(echo $redirect_url | sed -e 's/?/\n/g' | head -n1)"
    # split on question marks or ampersend, than filter on the specific param we are interested into
    local then_url="$(echo $redirect_url | sed -e 's/[?&]/\n/g' | grep "then=" | sed -e 's/then=//' )"
    local csrf=$(cat "$cookie_cached"  | grep -Po '(?<=\scsrf).*' | awk '{$1=$1;print}')

    # login on OpenShift and save output to delegate_permissions_form location
    local delegate_permissions_form="$(mktemp /tmp/syndesis_permissions.XXX.html)"
    curl --referer "$redirect_url" \
         --insecure \
         --location  \
         -H "Cookie: csrf=$csrf" \
         --data-urlencode username="$username"  \
         --data-urlencode password="developer" \
         --data-ascii then="$then_url" \
         --data-urlencode csrf="$csrf" \
         --cookie-jar "$cookie_new" \
         -i -v -o $delegate_permissions_form \
         "$login_url"  2>/dev/null

    # move the freshly created "ssn" cookie entry back to the main cookie
    tail -1 "$cookie_new" >> "$cookie_cached"

    local then_url=$(extract_and_escape "then" $delegate_permissions_form )
    local csrf=$(extract_and_escape "csrf" $delegate_permissions_form )
    local client_id=$(extract_and_escape "client_id" $delegate_permissions_form )
    local user_name=$(extract_and_escape "user_name" $delegate_permissions_form )
    local redirect_uri=$(extract_and_escape "redirect_uri" $delegate_permissions_form )

    local scopes=$(grep -Po '(?<=name="scope").*' $delegate_permissions_form | grep -Po '(?<=value=")[^"]+')
    local joined_scopes=""

    scopes=(${scopes// / })
    for i in "${!scopes[@]}"
    do
        joined_scopes="$joined_scopes --data-urlencode scope=${scopes[i]}"
    done

    # approve permission delegation, weaving all the params in the GET parameters

    curl --insecure \
         --location \
         -H 'dnt: 1'  \
         --cookie-jar "$cookie_cached" \
         --cookie "$cookie_cached" \
         --data-urlencode "then=$then_url" \
         --data-urlencode "csrf=$csrf" \
         --data-urlencode "client_id=$client_id" \
         --data-urlencode "user_name=$user_name" \
         --data-urlencode "redirect_uri=$redirect_uri" \
         --data-urlencode "approve=Allow+selected+permissions"  \
         $joined_scopes \
         -i -v -o /dev/null \
         "https://$openshift_ip_and_port/oauth/authorize/approve" 2>/dev/null
}

update_connector_manifest() {
    local connector=$1
    manifest_dir=$(appdir)/connector/$connector/target/classes/META-INF/syndesis/connector

    syndesis_server_pod=$(oc get pod -l syndesis.io/component=syndesis-server -o=jsonpath='{.items[0].metadata.name}' --ignore-not-found)
    if [ -z "$syndesis_server_pod" ]; then
        echo "Syndesis server pod not found"
        exit 1
    fi

    if [ -d "$manifest_dir" ]; then
        files=$(ls $manifest_dir | grep ".json")
        if [ -z "$files" ]; then
            echo "No manifest files found in $manifest_dir"
            exit 1
        fi

        for m in $files; do
            oc cp $manifest_dir/$m $syndesis_server_pod:/tmp/
            oc exec $syndesis_server_pod -- curl -X POST http://localhost:8181/connectors -H "Content-Type: application/json" -H "Syndesis-Xsrf-Token: awesome" -d @/tmp/$m
            echo "Manifest $m updated"
        done
    else
        echo "Cannot find manifest dir $manifest_dir"
        exit 1
    fi
}

dev::run() {
    source "$(basedir)/commands/util/openshift_funcs"

    if [ $(hasflag --debug) ]; then
        local name=$(readopt --debug)
        if [ -z "${name}" ]; then
            name="server"
        fi

        setup_oc

        local pod=$(oc get -o name pod -l syndesis.io/component=syndesis-${name})
        oc port-forward ${pod//*\//} 5005:5005
    elif [ $(hasflag --bump-camel) ]; then
        local camel_version=$(readopt --bump-camel)
        if [ -z "${camel_version}" ]; then
            echo "You must provide a valid camel version"
            exit 1
        fi
        appdir=$(appdir)
        # test if the new camel version is available on maven repo
        artifact_url=https://repository.jboss.org/nexus/content/groups/ea/org/apache/camel/camel-core/${camel_version}/camel-core-${camel_version}.pom
        artifact_ok=$(curl -X GET -I ${artifact_url} 2>/dev/null | head -n 1 | cut -d$' ' -f2)
        if [ ${artifact_ok} != 200 ]; then
          echo "Camel ${camel_version} is not available in ${artifact_url}"
          echo "Camel version did not change."
          exit 1
        fi
        current_camel=$(grep '<camel.version>' ${appdir}/pom.xml  | head -1 | cut -d '>' -f 2|cut -d '<' -f 1)
        echo "Changing Camel version from \"$current_camel\" to \"$camel_version\""
        sed -i "s/$current_camel/$camel_version/g" \
            ${appdir}/pom.xml \
            ${appdir}/extension/bom/pom.xml \
            ${appdir}/integration/bom/pom.xml
        next_cxf_version=$(curl -s "https://repository.jboss.org/nexus/content/groups/ea/org/apache/camel/camel-parent/${camel_version}/camel-parent-${camel_version}.pom" | sed -n 's/^.*<cxf-version>\(.*\)<\/cxf-version>/\1/p')
        current_cxf_version=$(sed -n 's/^.*<cxf\.version>\(.*\)<\/cxf\.version>/\1/p' "${appdir}/pom.xml")
        if [ "$current_cxf_version" != "$next_cxf_version" ]; then
          echo "Changing CXF version from \"$current_cxf_version\" to \"$next_cxf_version\""
          sed -i "s/$current_cxf_version/$next_cxf_version/g" \
              "${appdir}/pom.xml"
        fi
        git status
        echo "You should use git to add the files and commit them"
    elif [ $(hasflag --cookie) ]; then
        local cookie_cached="$HOME/.syndesis_api_cookie"
        if [ ! -f $cookie_cached ] || [ -n "$(hasflag --refresh)" ]; then
             create_api_cookie $cookie_cached
        fi
        echo $cookie_cached
    elif [ $(hasflag --version) ]; then
        oc get secret syndesis-global-config -o jsonpath={.data.syndesis} | base64 --decode
    elif [ $(hasflag --install-maven-mirror) ]; then
        install_maven_mirror
    elif [ $(hasflag --cleanup) ]; then
        echo -n Removing stale pods...
        local old_pods=$(oc get pods --field-selector=status.phase=Succeeded -o=jsonpath='{range .items[*]}{.metadata.name} ')
        if [ -n "$old_pods" ]; then
            oc delete pods $old_pods
        fi
        echo -e -n 'done\nRemoving stale builds...'
        set +e # we might not have system:admin privileges
        oc --as system:admin adm prune builds --confirm
        echo -e -n 'done\nRemoving stale deployments...'
        oc --as system:admin adm prune deployments --confirm
        echo -e -n 'done\nRemoving stale images...'
        if [ ! "$(oc --as system:admin -n default get route docker-registry -o name 2>/dev/null)" ]; then
            local cmd='oc --as system:admin expose service docker-registry -n default'
            local output=$(eval $cmd)
            if [ $? -ne 0 ]; then
                echo Unable to expose OpenShift registry via: $cmd
                echo $output
            fi
            sleep 5 # give the router time to reload the configuration
        fi
        local prune_cmd='oc --as system:admin adm prune images --registry-url=http://$(oc --as system:admin -n default get route docker-registry -o jsonpath={.spec.host}) --confirm 2>&1'
        # prevent lost line break when capturing the prune_cmd output
        IFS=''
        local prune_output=$(eval $prune_cmd)
        echo $prune_output
        # sometimes there are error trying to remove old images from registry, as
        # error deleting blob sha256:1daebdc712936afb9b1ba54cfd8b06ad55470e05ad346dc8156c448ed2223c6b from the registry: 401 Unauthorized
        # the following block retrieves the full image address to remove it
        if [[ $prune_output == *"error deleting blob"* ]]; then
            echo Error removing some images, forcing their removal.
            local imgs=`echo $prune_output|grep 'error deleting blob' | awk '{print $4}'  ORS='|' | sed 's/|$//g'`
            oc --as system:admin get images --show-kind=true|awk '{print $1}'|grep -E "$imgs" | while read img; do
                oc --as system:admin delete $img;
            done
        fi
        set -e

        if [ $(hasflag --nuke) ]; then
            # truncate jsondb tables
            oc exec -c postgresql $(oc get pod -l 'syndesis.io/component=syndesis-db' --no-headers=true -o=custom-columns=x:.metadata.name) -- bash -c "echo 'TRUNCATE jsondb; TRUNCATE config; TRUNCATE filestore; VACUUM FULL ANALYSE;' |psql -U syndesis"
            # restart syndesis-server pod
            oc delete $(oc get pod -l 'syndesis.io/component=syndesis-server' -o name)
            # delete all syndesis deployed objects
            oc delete $(oc get all -o name |grep -E '^[^/]+/(i-)')
        fi

        echo done
    elif [ $(hasflag --update-manifest) ]; then
        local connector=$(readopt --update-manifest)
        if [ -z "${connector}" ]; then
            echo "Cannot get the name of the connector manifest to sync"
            echo "Usage: syndesis dev --update-manifest <connector-name>"
            exit 1
        fi
        update_connector_manifest $connector
    fi
}
