#!/bin/bash

MHWDDEVICES=()

### Module Functions ###

MHWD_HEADING()
{
    echo '##' > "$1"
    echo '## Generated by mhwd - Manjaro Hardware Detection' >> "$1"
    echo '##' >> "$1"
    echo ' ' >> "$1"
    echo ' ' >> "$1"
}

MHWD_IS_DEVICE()
{
    local CCLASSID="$1"
    local CVENDORID="$2"
    local CDEVICEID="$3"

    for device in ${MHWDDEVICES[@]}; do
        while read CLASSID VENDORID DEVICEID BUSID; do
            if [ "$CCLASSID" == "$CLASSID" ] && [ "$CVENDORID" == "$VENDORID" ] && [ "$CDEVICEID" == "$DEVICEID" ]; then
                return 0
            fi
        done <<< "$(echo "$device" | sed 's/|/ /g')"
    done

    return 1
}

MHWD_FUNC_ON_MATCH()
{
    local CCLASSID="$1"
    local CVENDORID="$2"
    local CDEVICEIDS="$3"
    local RUNFUNC="$4"

    for device in ${MHWDDEVICES[@]}; do
        while read CLASSID VENDORID DEVICEID BUSID; do
            if [ "$CCLASSID" == "$CLASSID" ] && [ "$CVENDORID" == "$VENDORID" ]; then
                for d in $CDEVICEIDS; do
                    if [ "$d" == "$DEVICEID" ]; then
                        $RUNFUNC
                        return
                    fi
                done
            fi
        done <<< "$(echo "$device" | sed 's/|/ /g')"
    done
}

MHWD_DEVICE_BUS_ID()
{
    local CCLASSID="$1"
    local CVENDORID="$2"
    local ONLYFIRST="$3"

    for device in ${MHWDDEVICES[@]}; do
        while read CLASSID VENDORID DEVICEID BUSID; do
            if [ "$CVENDORID" == "*" ]; then
                VENDORID="*"
            fi

            if [ "$CCLASSID" == "$CLASSID" ] && [ "$CVENDORID" == "$VENDORID" ]; then
                echo "$BUSID"

                if [ "$ONLYFIRST" == "true" ] || [ "$ONLYFIRST" == "yes" ]; then
                    return
                fi
            fi
        done <<< "$(echo "$device" | sed 's/|/ /g')"
    done
}

MHWD_CHECK_KMODS()
{
    CONKMODS=""
    DEPKMODS=""

    if [ "${CONKMOD}" != "" ]; then
        for KERNEL in ${KERNELS} ; do
            if [ "$(pacman -Qq | grep -o ${KERNEL} -m1)" != "" ]; then
                for KMOD in ${CONKMOD} ; do
                    CONKMODS="${CONKMODS} ${KERNEL}-${KMOD}"
                done
            fi
        done
    fi
    if [ "${DEPKMOD}" != "" ]; then
        for KERNEL in ${KERNELS} ; do
            if [ "$(pacman -Qq | grep -o ${KERNEL} -m1)" != "" ]; then
                for KMOD in ${DEPKMOD} ; do
                    DEPKMODS="${DEPKMODS} ${KERNEL}-${KMOD}"
                done
            fi
        done
    fi
}

MHWD_CHECK_PKGS()
{
    local REMOVEPKGS=""

    for PKG in ${PACKAGES} ; do
        for RMPKG in $(pacman -Qq | grep ${PKG}) ; do
            if [ "${PKG}" == "${RMPKG}" ] ; then
               REMOVEPKGS="${REMOVEPKGS} ${RMPKG}"
            fi
        done
    done

    PACKAGES="${REMOVEPKGS}"
}

# Make them readonly
declare -fr MHWD_HEADING MHWD_PCI_BUS_ID

### Main ###
ARCH="$(uname -m)"
PARAM=$#
INCLUDEPATH="/var/lib/mhwd/scripts/include"
PACMAN="pacman --noconfirm"
SYNC=""
INSTALL=""
REMOVE=""
CONFIGPATH=""
CACHEPATH="/var/cache/pacman/pkg"
PMCONFIG="/etc/pacman.conf"
PMROOT="/"
PACKAGES=""
KERNELS=$(pacman -Qqs "^linux[0-9][0-9]?([0-9])$")
# lib32 config true/false
MHWD64CONF="/etc/mhwd-x86_64.conf"

# source lib32 true/false for x86_64
if [ "${ARCH}" == "x86_64" ];then
    if [ -f ${MHWD64CONF} ];then
        echo "Sourcing ${MHWD64CONF}"
        . ${MHWD64CONF}
    else
        echo "Using default"
        MHWD64_IS_LIB32="true"
    fi
    echo "Has lib32 support: ${MHWD64_IS_LIB32}"
fi

if [ "${PARAM}" -lt 1 ]; then
    echo "No Arguments!"
    exit 1
fi

for (( I=1; $I <= $PARAM; I++ ));do
    case "$1" in
        --install)
            INSTALL="true"
        ;;
        --remove)
            REMOVE="true"
        ;;
        --sync)
            SYNC="y"
        ;;
        --cachedir)
            shift
            CACHEPATH="$1"
        ;;
        --config)
            shift
            CONFIGPATH="$1"
        ;;
        --pmconfig)
            shift
            PMCONFIG="$1"
        ;;
        --pmroot)
            shift
            PMROOT="$1"
        ;;
        --device)
            shift
            MHWDDEVICES+=("$1")
        ;;
        "")    ;;
        *)
            echo "Wrong Argument: $1"
            exit 1
        ;;
    esac

    shift
done

# Set final variables
PACMAN="${PACMAN} --cachedir ${CACHEPATH} --config ${PMCONFIG} --root ${PMROOT}"

if [ "${CONFIGPATH}" != "" ] && [ -e "${CONFIGPATH}" ]; then
    echo "Sourcing ${CONFIGPATH}"
    . "${CONFIGPATH}"

    for classid in ${CLASSIDS} ; do
        echo "Processing classid: ${classid}"
        if [ -e "${INCLUDEPATH}/${classid}" ]; then
            echo "Sourcing ${INCLUDEPATH}/${classid}"
            . "${INCLUDEPATH}/${classid}"
        fi
    done
else
    exit 1
fi

if [ "${INSTALL}" == "true" ]; then
    # Run preinstall function
    if [ "`grep "pre_install" "${CONFIGPATH}" | cut -d"#" -f1 | cut -d"(" -f1 | grep "pre_install"`" == "pre_install" ]; then
       pre_install
    fi

    PACKAGES=""

    # Remove conflicts
    if [ "${CONFLDD}" != "" ]; then
        PACKAGES="${CONFLDD}"
    fi
    if [ "${ARCH}" == "x86_64" ] && [ "${CONFLDD_64}" != "" ]; then
        if [ "${MHWD64_IS_LIB32}" == "true" ];then
            PACKAGES="${PACKAGES} ${CONFLDD_64}"
        else
            PACKAGES="${PACKAGES}"
        fi
    fi

    # Check if packages are installed
    MHWD_CHECK_PKGS

    if [ "${PACKAGES}" != "" ]; then
        ${PACMAN} -Rdd ${PACKAGES}
        if [ "$?" -ne "0" ]; then
            echo "Error: pacman failed!"
            exit 1
        fi
    fi

    PACKAGES=""

    # Check for extramodules
    MHWD_CHECK_KMODS

    # Remove conflicts
    if [ "${CONFLICTS}" != "" ]; then
        PACKAGES="${CONFLICTS}"
    fi
    if [ "${ARCH}" == "i686" ] && [ "${CONFLICTS_32}" != "" ]; then
        PACKAGES="${PACKAGES} ${CONFLICTS_32}"
    fi
    if [ "${ARCH}" == "x86_64" ] && [ "${CONFLICTS_64}" != "" ]; then
        if [ "${MHWD64_IS_LIB32}" == "true" ];then
            PACKAGES="${PACKAGES} ${CONFLICTS_64}"
        else
            PACKAGES="${PACKAGES}"
        fi
    fi
    if [ "${CONKMODS}" != "" ]; then
        PACKAGES="${PACKAGES} ${CONKMODS}"
    fi

    # Check if packages are installed
    MHWD_CHECK_PKGS

    if [ "${PACKAGES}" != "" ]; then
        ${PACMAN} -Rs ${PACKAGES}
        if [ "$?" -ne "0" ]; then
            echo "Error: pacman failed!"
            exit 1
        fi
    fi

    PACKAGES=""

    [ "${OPTREMDEPENDS}" != "" ] && DEPENDS="${DEPENDS} ${OPTREMDEPENDS}"
    [ "${OPTREMDEPENDS_32}" != "" ] && DEPENDS_32="${DEPENDS_32} ${OPTREMDEPENDS_32}"
    [ "${OPTREMDEPENDS_64}" != "" ] && DEPENDS_64="${DEPENDS_64} ${OPTREMDEPENDS_64}"

    # Install dependencies
    if [ "${DEPENDS}" != "" ]; then
        PACKAGES="${DEPENDS}"
    fi
    if [ "${ARCH}" == "i686" ] && [ "${DEPENDS_32}" != "" ]; then
        PACKAGES="${PACKAGES} ${DEPENDS_32}"
    fi
    if [ "${ARCH}" == "x86_64" ] && [ "${DEPENDS_64}" != "" ]; then
        if [ "${MHWD64_IS_LIB32}" == "true" ];then
            PACKAGES="${PACKAGES} ${DEPENDS_64}"
        else
            PACKAGES="${PACKAGES}"
        fi
    fi
    if [ "${DEPKMODS}" != "" ]; then
        PACKAGES="${PACKAGES} ${DEPKMODS}"
    fi

    if [ "${PACKAGES}" != "" ]; then
        ${PACMAN} --needed -S${SYNC} ${PACKAGES}
        if [ "$?" -ne "0" ]; then
            echo "Error: pacman failed!"
            exit 1
        fi
        ${PACMAN} -D --asexplicit ${PACKAGES}
        if [ "$?" -ne "0" ]; then
            echo "Error: pacman failed!"
            exit 1
        fi
    elif [ "${SYNC}" != "" ]; then
        ${PACMAN} -S${SYNC}
    fi

    # Run postinstall function
    if [ "`grep "post_install" "${CONFIGPATH}" | cut -d"#" -f1 | cut -d"(" -f1 | grep "post_install"`" == "post_install" ]; then
       post_install
    fi
fi

if [ "${REMOVE}" == "true" ]; then
    # Run preremove function
    if [ "`grep "pre_remove" "${CONFIGPATH}" | cut -d"#" -f1 | cut -d"(" -f1 | grep "pre_remove"`" == "pre_remove" ]; then
       pre_remove
    fi

    PACKAGES=""
    OPTREMPACKAGES=""

    # Check for extramodules
    MHWD_CHECK_KMODS

    # Remove dependencies
    if [ "${DEPENDS}" != "" ]; then
        PACKAGES="${DEPENDS}"
    fi
    if [ "${ARCH}" == "i686" ] && [ "${DEPENDS_32}" != "" ]; then
        PACKAGES="${PACKAGES} ${DEPENDS_32}"
    fi
    if [ "${ARCH}" == "x86_64" ] && [ "${DEPENDS_64}" != "" ]; then
        if [ "${MHWD64_IS_LIB32}" == "true" ];then
            PACKAGES="${PACKAGES} ${DEPENDS_64}"
        else
            PACKAGES="${PACKAGES}"
        fi
    fi
    if [ "${DEPKMODS}" != "" ]; then
        PACKAGES="${PACKAGES} ${DEPKMODS}"
    fi
    if [ "${CONKMODS}" != "" ]; then
        PACKAGES="${PACKAGES} ${CONKMODS}"
    fi

    # Check if packages are installed
    MHWD_CHECK_PKGS

    if [ "${PACKAGES}" != "" ]; then
        ${PACMAN} -Rs ${PACKAGES}
        if [ "$?" -ne "0" ]; then
            echo "Error: pacman failed!"
            exit 1
        fi
    fi

    PACKAGES=""

    # Remove OPTREM dependencies
    # Has to be run after normal dependencies were removed, since said dependencies may optionally depend on an OPTREM package
    if [ "${OPTREMDEPENDS}" != "" ]; then
        OPTREMPACKAGES="${OPTREMDEPENDS}"
    fi
    if [ "${ARCH}" == "i686" ] && [ "${OPTREMDEPENDS_32}" != "" ]; then
        OPTREMPACKAGES="${OPTREMPACKAGES} ${OPTREMDEPENDS_32}"
    fi
    if [ "${ARCH}" == "x86_64" ] && [ "${OPTREMDEPENDS_64}" != "" ]; then
        if [ "${MHWD64_IS_LIB32}" == "true" ]; then
            OPTREMPACKAGES="${OPTREMPACKAGES} ${OPTREMDEPENDS_64}"
        else
            OPTREMPACKAGES="${OPTREMPACKAGES}"
        fi
    fi

    if [ "${OPTREMPACKAGES}" != "" ]; then
        ${PACMAN} -D --asdeps ${OPTREMPACKAGES}
        if [ "$?" -ne "0" ]; then
            echo "Error: pacman failed!"
            exit 1
        fi
    fi

    # Check if packages are installed
    MHWD_CHECK_PKGS

    if [ "${PACKAGES}" != "" ]; then
        ${PACMAN} -Rs ${PACKAGES}
        if [ "$?" -ne "0" ]; then
            echo "Error: pacman failed!"
            exit 1
        fi
    fi

    # Run postremove function
    if [ "`grep "post_remove" "${CONFIGPATH}" | cut -d"#" -f1 | cut -d"(" -f1 | grep "post_remove"`" == "post_remove" ]; then
       post_remove
    fi
fi

exit 0
