#!/bin/bash

debug=1

__action_func_cb=(
    "check_pcie_exists"
    "get_confict_drvname"
    "check_arch_exist"
    "check_kver_exist"
    "check_productname_exit"
    "check_boardname_exit"
    "get_drv_name"
    "get_overlay_install_flag"
    "get_keepconf_install_flag"
    "get_extra_action"
    "get_extra_info"
    )

fix_nvidia_gpudrv() {
    # 检查是否存在 deepin-nvidia-installer
    if [ ! -e /usr/sbin/deepin-nvidia-installer ]; then
    	return
    fi

    local step=${1}
    if lspci -n | grep -i 10de | egrep -i '.*03(80|0[0-2])' ;then
        if [[ ${step} == "--first-boot" ]]; then
            deepin-nvidia-installer autoinstall
        else
            deepin-nvidia-installer ${step} autoinstall
        fi
        logger "fix_nvidia_gpudrv"  $?
    fi
}

exec_plugin() {
    [[ -z $1 ]] && return
    PWD=$(pwd)
    cd ${plugindir}
    . "$1"
    ret=$?
    cd ${PWD}
    return $ret
}

fix_one()
{
    if [[ $dev_found  -eq 1 ]] && [[ $arch_found -eq 1 ]] && \
         [[ $kver_found -eq 1 ]] && \
         [[ $product_name_found -eq 1 ]] && \
         [[ $board_name_found -eq 1 ]]; then

         echo "$line" >&8

        if [[ ${#confict_act[@]} > 0 ]]; then
            for i in $(seq 0 $((${#confict_act[@]}-1))); do
                ${confict_act[$i]}
                logger "${confict_act[$i]}" $?
            done
        fi

        if [[ ${#extra_act[@]} > 0 ]]; then
            for i in $(seq 0 $((${#extra_act[@]}-1))); do
                exec_plugin "${extra_act[$i]}"
                logger "${extra_act[$i]}" $?
            done
        fi

        if [[ ! -z "${install_drv}" ]]; then
            if [ $keepconf -eq 1 ]; then
                save_install_one_drv "${install_drv}"
            else
                unsave_install_one_drv "${install_drv}"
            fi
            logger "install ${install_drv}" $?
        fi

        if [[ ! -z "${extra_info}" ]]; then
            echo "$extra_info"
        fi

        echo >&8
    fi
}

debugger()
{
    if [[ $debug -ne 1 ]]; then
        return
    fi
    echo "$line"
    echo "dev_found="$dev_found
    echo "arch_found="$arch_found
    echo "kver_found="$kver_found
    echo "product_name_found="$product_name_found
    echo "board_name_found="$board_name_found
    echo "install_drv="$install_drv
    echo "overlay="$overlay
    echo "keepconf="$keepconf
    echo "extra_info="$extra_info

    echo "confict_act:${#confict_act[@]}"
    if [[ ${#confict_act[@]} > 0 ]]; then
        for i in $(seq 0 $((${#confict_act[@]}-1))); do
            echo " [${i}]=${confict_act[$i]}"
        done
    fi

    echo "extra_act:${#extra_act[@]}"
    if [[ ${#extra_act[@]} > 0 ]]; then
        for i in $(seq 0 $((${#extra_act[@]}-1))); do
            echo " [${i}]=${extra_act[$i]}"
        done
    fi
}

do_all_fix()
{
    declare -f cb
    cat "${1}" | grep -v ^# | grep -v ^$ | while read line
    do
        dev_found=0
        arch_found=0
        kver_found=0
        product_name_found=0
        board_name_found=0

        declare -a confict_act
        install_drv=""
        overlay=0
        keepconf=1
        declare -a extra_act
        extra_info=""
        OIFS=$IFS
        IFS='|' read -ra arr < <(echo "$line")
        IFS=$OIFS

        [[ ${#arr[@]} != ${#__action_func_cb[@]} ]] && continue

        for i in $(seq 0 $((${#arr[@]}-1)))
        do
            cb="${__action_func_cb[$i]}"
            if [[ "${1}" = "${usbconf}" ]] && [[ "${cb}" = "check_pcie_exists" ]]; then
                cb="check_usb_exists"
            fi
            "${cb}" "${arr[$i]}"
        done

        debugger
        fix_one

        [[ $debug -eq 1 ]] && echo
        unset extra_info
        unset extra_act
        unset keepconf
        unset overlay
        unset install_drv
        unset confict_act
    done
}

check_pcie_exists()
{
    OIFS=$IFS
    IFS=',' read -ra pcie_arr < <(echo "$1")
    IFS=$OIFS

    if [[ ${#pcie_arr[@]} -eq 0 ]]; then
        dev_found=1
        return
    fi

    for u in "${pcie_arr[@]}"; do
        un=$(echo "${un}"| tr -d ' ')
        if [[ "${un}" == "*" ]]; then
            dev_found=1
            return
        fi

        if is_pci_exists "$u"; then
            dev_found=1
            break
        fi
    done

    return
}

check_usb_exists()
{
    OIFS=$IFS
    IFS=',' read -ra usb_arr < <(echo "$1")
    IFS=$OIFS

    if [[ ${#usb_arr[@]} -eq 0 ]]; then
        dev_found=1
        return
    fi

    for u in "${usb_arr[@]}"; do
        un=$(echo "${u}"| tr -d ' ')
        if [[ "${un}" == "*" ]]; then
            dev_found=1
            return
        fi

        if is_usb_exists "$u"; then
            dev_found=1
            break
        fi
    done

    return
}

get_confict_drvname()
{
    OIFS=$IFS
    IFS=',' read -ra confict < <(echo "$1")
    IFS=$OIFS

    if [[ ${#confict[@]} -eq 0 ]]; then
        return
    fi

    declare -i i=0
    for u in "${confict[@]}"; do
        un=$(echo "${u}"| tr -d ' ')
        if [[ "${un}" == "*" ]]; then
            break;
        fi
        confict_act[$i]="apt purge ${u} -y"
        ((i++))
    done

    return
}

check_arch_exist()
{
    OIFS=$IFS
    IFS=',' read -ra arch_arr < <(echo "$1")
    IFS=$OIFS

    if [[ ${#arch_arr[@]} -eq 0 ]]; then
        arch_found=1
        return
    fi

    cur=$(arch)
    for u in "${arch_arr[@]}"; do
        un=$(echo "${u}"| tr -d ' ')
        if [[ "${un}" == '*' ]]; then
            arch_found=1
            break
        fi

        if [[ $cur == $u ]]; then
            arch_found=1
            break
        fi
    done
    return
}

check_kver_exist()
{
    OIFS=$IFS
    IFS=',' read -ra kv_arr < <(echo "$1")
    IFS=$OIFS

    if [[ ${#kv_arr[@]} -eq 0 ]]; then
        kver_found=1
        return 0
    fi

    cur=$(uname -a)
    cur=$(echo "$cur"| awk '{print $3}')
    cur=$(echo "$cur"| awk -F'-' '{print $1}')
    cur=$(echo "$cur"| awk -F'.' '{print $1$2}')
    for u in "${kv_arr[@]}"; do
        un=$(echo "${u}"| tr -d ' ')
        if [[ "${un}" == "*" ]]; then
            kver_found=1
            break
        fi

        u=$(echo $u | awk -F'.' '{print $1$2}')
        if [[ $cur == $u ]]; then
            kver_found=1
            break
        fi
    done

    return
}

check_productname_exit()
{
    OIFS=$IFS
    IFS=',' read -ra pdname_arr < <(echo "$1")
    IFS=$OIFS

    if [[ ${#pdname_arr[@]} -eq 0 ]]; then
        product_name_found=1
        return 0
    fi

    cur=$(cat /sys/class/dmi/id/product_name)
    for u in "${pdname_arr[@]}"; do
        un=$(echo "${u}"| tr -d ' ')
        if [[ "${un}" == "*" ]]; then
            product_name_found=1
            break
        fi

        if [[ ${#u} -lt ${min_wildcard_len} ]]; then
            continue
        fi

        if is_productname_exists "$u"; then
            product_name_found=1
            break
        fi
    done
    return
}

check_boardname_exit()
{
    OIFS=$IFS
    IFS=',' read -ra bdname_arr < <(echo "$1")
    IFS=$OIFS

    if [[ ${#bdname_arr[@]} -eq 0 ]]; then
        board_name_found=1
        return 0
    fi

    cur=$(cat /sys/class/dmi/id/board_name)
    for u in "${bdname_arr[@]}"; do
        un=$(echo "${u}"| tr -d ' ')
        if [[ "${un}" == "*" ]]; then
            board_name_found=1
            break
        fi

        if [[ ${#u} -lt ${min_wildcard_len} ]]; then
            continue
        fi

        if is_boardname_exists "$u"; then
            board_name_found=1
            break
        fi
    done
    return
}

get_drv_name()
{
    __tmp=$(echo "${1}"| tr -d ' ')
    if [[ "${__tmp}" == "*" ]]; then
        return
    fi
    if [[ "${__tmp}X" == "X" ]]; then
        return
    fi
    install_drv="${1}"
    return
}

get_overlay_install_flag()
{
    __tmp=$(echo "${1}"| tr -d ' ')

    case ${__tmp} in
        [yY][eE][sS]|[yY])
            overlay=1
            ;;
        *)
            overlay=0
            ;;
    esac
}

get_keepconf_install_flag()
{
    __tmp=$(echo "${1}"| tr -d ' ')

    case ${__tmp} in
        [nN][nN]|[nN])
            keepconf=0
            ;;
        *)
            keepconf=1
            ;;
    esac
}

get_extra_action()
{
    OIFS=$IFS
    IFS=',' read -ra extra_act_arr < <(echo "$1")
    IFS=$OIFS

    if [[ ${#extra_act_arr[@]} -eq 0 ]]; then
        return
    fi

    declare -i i=0
    for u in "${extra_act_arr[@]}"; do
        un=$(echo "${u}"| tr -d ' ')
        if [[ "${un}" == "*" ]]; then
            break;
        fi
        extra_act[$i]="${u}"
        ((i++))
    done
}

get_extra_info()
{
    __tmp=$(echo "${1}"| tr -d ' ')
    if [[ "${__tmp}" == "*" ]]; then
        return
    fi
    if [[ "${__tmp}X" == "X" ]]; then
        return
    fi
    extra_info="${1}"
    return
}
