#!/bin/bash
# set -x 

source ./log_helpers
source ./general_utils


# if [ ${git_helpers_sourced:-1} = "1" ]; then
#    readonly git_helpers_sourced=${BASH_SOURCE[0]}

readonly repository_already_up_to_date=2

#
exec_git_command () {
    local func="${FUNCNAME[0]}"
    log_debug "$func:${LINENO} exec-ing [$*]"
    
    local __git_result=$(exec_process_substitution $*)
    log_debug "$func:${LINENO} result=$__git_result"

    printf '%s' "$__git_result"
}

# 
latest_commit () {
    local func="${FUNCNAME[0]}"
    # git reflog -> 46c5896 HEAD@{0}: commit: Made update_helpers executable
    local c=$(git reflog | grep "HEAD@{0}" | cut -d" " -f1)
    if ! [ -z "$c" ]; then
        if grep -qE "^[[:xdigit:]]{6,}$" <<< $c; then
            log_debug "$func:${LINENO} commit -> $c"
            printf "%s\n" "$c"
        else
            log_crit "$func:${LINENO} wrong format for commit c=$c"
        fi
    else 
        log_crit "$func:${LINENO} 'git reflog' result empty"
    fi
}

# fallback if something went wrong: revert to last valid commit
revert_to_commit_before_pull () {
    local func="${FUNCNAME[0]}"
    if ! [ -z "$commit_before_pull" ]; then
        if grep -qE "^[[:xdigit:]]{6,}$" <<< $commit_before_pull; then
            `git reset --hard "$commit_before_pull"`
            if [ $? -eq 0 ]; then
                log_info "$func: git reset --hard $commit_before_pull"
                return 0
            fi
            log_crit "$func: 'git reset --hard $commit_before_pull' failed!"
        fi
        log_crit "$func: wrong format for commit_before_pull"
    fi
    log_crit "$func: empty commit_before_pull"
    return 1
}
# revert_to_commit_before_pull

# clone the customer repository in ./workspace.
# this is done only once.
# 
# Cloning into 'customer_281'...
# remote: Enumerating objects: 1087, done.
# remote: Counting objects: 100% (1087/1087), done.
# remote: Compressing objects: 100% (946/946), done.
# remote: Total 1087 (delta 404), reused 0 (delta 0), pack-reused 0
# Receiving objects: 100% (1087/1087), 103.27 KiB | 873.00 KiB/s, done.
# Resoving deltas: 100% (410/410), done.
#
clone_customer_repository () {
    local func="${FUNCNAME[0]}"
    if [ "$PWD" = "$WORKING_DIRECTORY" ]; then
        mkdir -p "./$WORKSPACE_DIR"
        # check if the directory is empty. If so, clone the
        # customer repository
        if ! find ./$WORKSPACE_DIR -mindepth 1 -maxdepth 1 | read; then
            log_debug "$func:${LINENO} cloning ${1} ..."
            if cd "./$WORKSPACE_DIR"
            then
                $(exec_git_command git clone "$1")
                if [ $? -eq 0 ]; then
                    log_debug "$func:${LINENO} cloning ${1} done"
                    GIT_CLONE_EXECUTED=1
                    rm -f $GIT_PULL_TMP
                    rm -f $OPKG_CMDS_TMP
                    # after cloning, cd into repository, and re-initialize,
                    # setting the work-tree as "/". This has the effect that
                    # a "git pull" will automatically fetched files in the
                    # corresponding sytem-folders.
                    if cd ${CUSTOMER_ID_BASE_DIR}; then
                        # configure hooks directory
                        exec_git_command git config core.hooksPath .githooks
                        exec_git_command git checkout "$LOCAL_BRANCH"
                        if [[ $? -eq 0 ]]; then
                            log_debug "$func:${LINENO} checked out local branch $LOCAL_BRANCH"
                            exec_git_command git config core.worktree "/"
                            if [[ $? -eq 0 ]]; then
                            	log_debug "$func:${LINENO} configured worktree"
                                exec_git_command git fetch --all
                       	        if [[ $? -eq 0 ]]; then
                            	    log_debug "$func:${LINENO} fetch repository"
                                    exec_git_command git reset --hard "$LOCAL_BRANCH"
                       	            if [[ $? -eq 0 ]]; then
                            	    	log_debug "$func:${LINENO} reset --hard $LOCAL_BRANCH"
                                        CLONE_CUSTOMER_REPOSITORY=true
                                        log_debug "$func:${LINENO} re-init of ${1} done"
                                        cd_home; return 0
			                        fi
		    	                fi
                            fi
		                fi
                    fi
                fi
                cd_home; return 1
            fi
        else
            # the directory is not empty, so we assume the
            # customer-repository has been cloned already
            if ! [[ -d "./${WORKSPACE_DIR}/$CUSTOMER_ID" ]]; then
                log_fatal "$func:${LINENO} $PWD $WORKSPACE_DIR/$CUSTOMER_ID"\
                    "wrong repository: $(ls -d './${WORKSPACE_DIR}/*')"
            else
                local __m="./${WORKSPACE_DIR}/$CUSTOMER_ID exists"
                log_debug "$func:${LINENO} $__m"
                return 0
            fi
        fi
    fi

    update_psa_clone_error  # message to ISMAS
    return $? 
}
# clone_customer_repository ->
# https://git.mimbach49.de/GerhardHoffmann/customer_281.git

cd_customer_repository () {
    local func="${FUNCNAME[0]}"
    # has to be called in WORKING_DIRECTORY
    cd "$WORKING_DIRECTORY"
    if [ "$PWD" = "${WORKING_DIRECTORY}" ]; then
        repository_dir="./$WORKSPACE_DIR/$CUSTOMER_ID"
        if ! [[ -d "$repository_dir" ]]; then
            log_crit "$func:${LINENO}: $repository_dir does not exist!"
            return 1
        fi
        
        if ! { cd $repository_dir; } ; then
            log_crit "$func:${LINENO}: cannot cd to $repository_dir!"
            return 1
        fi

        log_debug "$func:${LINENO}: cd to $repository_dir!"
        return 0
    fi
    return 1
}

cd_home () {
    if cd - &>/dev/null ; then
        return 0
    fi
    return 1
}

pull_customer_repository () {
    local func="${FUNCNAME[0]}"

    if ! cd_customer_repository; then
        return 1
    fi

    #local commit_before_pull=$(latest_commit)
    #if [ -z $commit_before_pull ]; then
    #    log_warn "$func:${LINENO}: commit_before_pull empty"
    #    cd_home ; return 1
    #fi
    #log_debug "$func:${LINENO}: commit_before_pull=$commit_before_pull"

    rm -f "$OPKG_CMDS_TMP"
    rm -f "$GIT_PULL_TMP"

    log_debug "$func:${LINENO}: executing 'git pull'..."
    exec_git_command 'git pull'

    # GIT_PULL_TMP created by hook post-merge. it contains the names of the
    # changed files.
    if [[ -f $GIT_PULL_TMP ]]; then
        cd_home; return 0
    fi

    log_warn "$func:${LINENO}: no data fetched form repository"
    cd_home; return 1
}
# pull_customer_repository customer_281

changed_file_names () {
    local func="${FUNCNAME[0]}"
    if  cd_customer_repository ; then
        local git_res=$(exec_git_command 'git diff --stat master@{1} master')
        git_res=${git_res//[$'\r\n\t']/ }
        log_debug "$func:${LINENO}: git_res=$git_res"
        local file_names=""
        for f in ${KNOWN_FILES[@]} ; do 
            if grep -qE "${f}" <<< "$git_res"; then
                if ! [ -z $file_names ]; then
                    file_names="$f $file_names"
                else
                    file_names="$f"
                fi
                log_debug "$func:${LINENO}: $f found in $git_res"
            fi
        done    

        cd_home; log_debug "$func:${LINENO}: file_names=$file_names" ;
        printf '%s' "$file_names" 
    else
        log_crit "$func:${LINENO}: cannot cd to $customer_repository "\
            "while in $PWD"
    fi
}

get_blob () {   # get the blob of the file(name) passed as $1
                # note: this can be used for any file in the filesystem
    echo $(git hash-object $1)
}

get_commit_for_blob () {
    blob=$(get_blob $1)
    if [ ! -z $blob ]; then
        # search for the blob in all commits for the file(name) $1
        echo $(echo $(git log --all --pretty=format:%H -- $1) |
               xargs -I{} sh -c "git ls-tree {} -- $1         |
               grep -q $blob && echo {}")
    fi
}