if [ -z $HOME ]; then
    echo "Cannot find your user's home directory..."
    exit 1
fi

SECRETS=$HOME/.unlocker/.secrets
LOCKED_SECRETS="$SECRETS.lock"

if [ "x$1" = "xhelp" ]; then
    echo "              _            _             "
    echo "  _   _ _ __ | | ___   ___| | _____ _ __ "
    echo " | | | | '_ \| |/ _ \ / __| |/ / _ \ '__|"
    echo " | |_| | | | | | (_) | (__|   <  __/ |   "
    echo "  \__,_|_| |_|_|\___/ \___|_|\_\___|_|   "
    echo ""
    echo "Unlocker v$VERSION $(uname -op)"
    echo ""
    echo "THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR"
    echo "IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,"
    echo "FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE"
    echo "AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER"
    echo "LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,"
    echo "OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE"
    echo "SOFTWARE."
    echo ""
    echo "  Please report bugs at $HOMEPAGE"
    echo ""
    echo "Usage:"
    echo "  service [user@]host[:port]  - Unlock server if credentials are known"
    echo ""
    echo "Examples:"
    echo "  redis 127.0.0.1:6379        - Connect to local Redis with an available user"
    echo "  mysql 127.0.0.1             - Connect to MySQL with any available user"
    echo "  mysql guest@database:3306   - Connect to MySQL on port 3306 with user guest"
    echo "  ssh root@yourserver.tld     - Connect to yourserver.tld with root user"
    echo "  ssh yourserver.tld          - Connect to yourserver.tld with available user"
    echo ""
    exit 0
fi

if ! [ -x "$(command -v gpg)" ]; then
    echo "Cannot decrypt secrets..."
    echo "Please install gpg and try again"
    echo "Closing..."
    exit 1
fi

if [ $(ls -l $LOCKED_SECRETS 2> /dev/null | wc -l) = "1" ]; then
    gpg -o $SECRETS --decrypt $LOCKED_SECRETS
    if [ $? != "0" ]; then
        echo "Failed to decrypt secrets..."
        echo "Closing..."
        exit 1
    fi
    rm -f $LOCKED_SECRETS
    if [ -z $1 ]; then
        echo "Secrets are now unlocked"
        exit 0
    fi
fi

if [ $(ls -l $SECRETS 2> /dev/null | wc -l) = "0" ]; then
    echo "Either unlocker has not been initialized, either secrets are missing"
    echo "Try unlock help and unlocker -h"
    echo "Closing..."
    exit 1
fi

is_installed ()
{
    if [ "x$1" = "x?" ]; then
        shift
    fi
    if [ -z $1 ]; then
        echo "Missing service to check if is installed..."
        exit 2
    elif ! [ -x "$(command -v $1)" ]; then
        echo "Cannot find $1..."
        echo "Please install $1 and try again"
        exit 1
    elif [ "x$DEBUG" = "x*" ]; then
        echo "$1 is installed..."
    fi
}

get_passkey()
{
    if [ "x$DEBUG" = "x*" ]; then
        echo $@ | unlocker
    else
        echo $@ | unlocker 2> /dev/null
    fi
}

get_password ()
{
    echo $1 | sed -En 's/^\.(.*)/\1/pg' | python -m base64 -d
}

get_private_key ()
{
    echo $1 | sed -En 's/^>(.*)/\1/pg' | python -m base64 -d
}

unlock_service ()
{
    mkdir -p /tmp/.unlocker
    case $1 in
        ssh) {
            params=$(echo $2 | sed -En 's/(.+)@(.+):(.+)/\1@\2 -p\3/gp')
            if [ -z "$params" ]; then
                params=$2
            fi
            if [ "x$DEBUG" = "xssh" -o "x$DEBUG" = "x*" ]; then
                params="-v $params"
            fi
            passkey=$(get_passkey ssh://$2)
            if [ -z "$passkey" ]; then
                echo "Cannot unlock server because passkey is missing..."
                echo "Recovering..."
                echo "Press any key to continue adding a password or a private key and store"
                echo "it for later use, otherwise exit with ^C or add it to unlocker manually"
                read -p "" anykey
                echo "Choose how to connect:"
                echo "  1) I have a password"
                echo "  2) I have a privatekey"
                echo ""
                read -p "Type number: " auth
                args=$(echo $2 | sed -En 's/(.+)@(.+):(.+)/-u \1 -H \2 -p \3/pg')
                if [ -z "$args" ]; then
                    args=$(echo $2 | sed -En 's/(.+)@(.+)/-u \1 -H \2 -p 22/pg')
                fi
                case $auth in
                    1) {
                        args="-a password $args"
                    }
                    ;;
                    2) {
                        args="-a privatekey $args"
                    }
                    ;;
                    *) {
                        echo "Unsuported authentification method..."
                        exit 1
                    }
                    ;;
                esac
                unlocker append $args
                passkey=$(get_passkey ssh://$2)
            fi
            password=$(get_password $passkey)
            if [ -z "$password" ]; then
                privatekey=$(get_private_key $passkey)
                if [ -z "$privatekey" ]; then
                    echo "Cannot understand authentification method for $2"
                    echo "It may not be supported by unlocker or it may corrupted"
                    exit 1
                fi
                secret_file=/tmp/.unlocker/$(date +%s).pk
                get_private_key $passkey | tee $secret_file > /dev/null
                chmod 0400 $secret_file
                params="-i $secret_file $params"
                is_installed ? ssh
                ssh $params
            else
                export SSHPASS=$password
                is_installed ? sshpass
                sshpass -e ssh $params
                unset SSHPASS
            fi
        }
        ;;
        mysql) {
            params=$(echo $2 | sed -En 's/(.+)@(.+):(.+)/-h\2 -P\3 -u\1/gp')
            if [ -z "$params" ]; then
                params=$(echo $2 | sed -En 's/(.+)@(.+)/-h\2 -u\1/gp')
            fi
            if [ "x$DEBUG" = "xmysql" -o "x$DEBUG" = "x*" ]; then
                params="-v $params"
            fi
            passkey=$(get_passkey mysql://$2)
            if [ -z "$passkey" ]; then
                echo "Cannot unlock server because passkey is missing..."
                echo "Recovering..."
                echo "Press any key to continue adding a password and store it for later"
                echo "use, otherwise exit with ^C or add it to unlocker manually"
                read -p "" anykey
                args=$(echo $2 | sed -En 's/(.+)@(.+):(.+)/-u \1 -H \2 -p \3/pg')
                if [ -z "$args" ]; then
                    args=$(echo $2 | sed -En 's/(.+)@(.+)/-u \1 -H \2 -p 3306/pg')
                fi
                unlocker append $args -a password
                passkey=$(get_passkey mysql://$2)
            fi
            password=$(get_password $passkey)
            if [ -z "$password" ]; then
                echo "Cannot understand authentification method for $2"
                echo "It may not be supported by unlocker or it may corrupted"
                exit 1
            else
                params="-p$password $params"
            fi
            is_installed ? mysql
            mysql $params
        }
        ;;
        redis) {
            params=$(echo $2 | sed -En 's/(.+)@(.+):(.+)/-h \2 -p \3/gp')
            if [ -z "$params" ]; then
                params=$(echo $2 | sed -En 's/(.+):(.+)/-h \1 -p \2/gp')
                if [ -z "$params" ]; then
                    params="-h $2"
                fi
            fi
            if [ "x$DEBUG" = "xredis" -o "x$DEBUG" = "x*" ]; then
                echo "Unlocker doesn't support verbose mode for Redis"
            fi
            passkey=$(get_passkey redis://_@$2)
            if [ -z "$passkey" ]; then
                echo "Cannot unlock server because passkey is missing..."
                echo "Recovering..."
                echo "Press any key to continue adding a password and store it for later"
                echo "use, otherwise exit with ^C or add it to unlocker manually"
                read -p "" anykey
                args=$(echo $2 | sed -En 's/(.+)@(.+):(.+)/-H \2 -p \3/pg')
                if [ -z "$args" ]; then
                    args=$(echo $2 | sed -En 's/(.+):(.+)/-H \1 -p \2/pg')
                    if [ -z "$args" ]; then
                        args="-H $2 -p 6379"
                    fi
                fi
                unlocker append $args -a password -u _
                passkey=$(get_passkey redis://_@$2)
            fi
            password=$(get_password $passkey)
            if [ -z "$password" ]; then
                echo "Cannot understand authentification method for $2"
                echo "It may not be supported by unlocker or it may corrupted"
                exit 1
            else
                params="$params -a $password"
            fi
            is_installed ? redis-cli
            redis-cli $params
        }
        ;;
        *) {
            is_installed ? $1
            if [ $? != 0 ]; then
                echo "$1 is installed on your system, but is not supported by Unlocker"
                echo "Help by submiting an implementation or a request at $HOMEPAGE"
                echo "Closing..."
                exit 1
            fi
        }
        ;;
    esac
    rm -rf /tmp/.unlocker
}

if [ -z $1 ]; then
    echo "Nothing to unlock (try help)"
    echo "Closing..."
    exit 1
fi

if [ -z $2 ]; then
    echo "Server address required (try help)"
    echo "Closing..."
    exit 1
fi

is_installed ? python
is_installed ? pip
is_installed ? unlocker

echo "Trying to unlock $2..."
unlock_service $@
echo "Successfully closed connection to $2..."
