upd_msg(){
    TTL_UPDCNT=0
    SOLUS_UPCNT=0
    FLATPAK_UPCNT=0
    UPCNT_FP=0
    UPMSG="${CSS_BOLDBRIGHT}${MSG_UPD_AVAIL_UPD}: ${MSG_UPD_NONE}${CSS_RESET}"

    if [ ! -f "$UP_LOCK_FILE" ] && [ -f "$UP_CACHE_FILE" ]; then
        . "$UP_CACHE_FILE"
    fi


    if [ "$TTL_UPDCNT" -gt 0 ]; then
        UPMSG_FP=""
        if [ "$FLATPAK_UPCNT" -gt 0 ]; then
            UPMSG_FP=" | $MSG_UPD_FLATPAK: $FLATPAK_UPCNT"
        fi

        UPMSG="${CSS_BOLDBRIGHT}${MSG_UPD_AVAIL_UPD}: ${CSS_GREENB}${MSG_UPD_SYSTEM}: ${SOLUS_UPCNT} ${UPMSG_FP}${CSS_RESET}"
    fi

    echo -e "$UPMSG"


    if [ "$1" == "list" ] && [ "$TTL_UPDCNT" -gt 0 ]; then
        hr "w30"
        SS_HASUP_LIST=1
        if [ ! -f "$UL_CACHE_FILE" ]; then
              echo -e "$MSG_UPD_DISCO\n\n"
              if [ "$SOLUS_UPCNT" -gt 0 ]; then
                echo -e "${CSS_BOLDBRIGHT}${CSS_CYAN}📦 Solus:${CSS_RESET}"
                if [ "$SS_SOLUS_REPO" == "Unstable" ]; then
                  echo -e "${CSS_YELLOW}""$MSG_UPD_WARN""${CSS_RESET}\n"
                fi
                eopkg lu | awk -F' - ' '{print "\033[1;92m" $1 "\033[0m\n" $2"\n"}' | fold -s -w 70
              fi

              if [ "$FLATPAK_UPCNT" -gt 0 ]; then
               echo -e "${CSS_BOLDBRIGHT}${CSS_CYAN}📦 Flatpak:${CSS_RESET}"
               flatpak remote-ls --updates --columns=application,name,version | grep -vFw -f <(flatpak mask | awk '{print $1}') | sed 's/^[^ \t]*[ \t]*//'  | fold -s -w 70
               #flatpak remote-ls --updates --columns=name,version | fold -s -w 70
              fi
        else
            UPLIST=$(<"$UL_CACHE_FILE")
            echo -e "$UPLIST" | fold -s -w 70
        fi
    else
      echo -e ""
    fi
}

check_updates(){
    if [ "$SS_DISABLE_UPCHK" -eq 0 ]; then
        echo "#Lock file for update checks" > "$UP_LOCK_FILE"
        if [ "$1" == "system" ] || [ ! -f "$UP_CACHE_FILE" ] || [ -n "$(find "$UP_CACHE_FILE" -mmin +5 2>/dev/null)" ]; then

            PREV_UPCNT_TTL=0;

            if [ -f "$UP_CACHE_FILE" ]; then
                . "$UP_CACHE_FILE"
                PREV_UPCNT_TTL="$PREV_UPCNT_TTL"
            fi

            echo "#Update Count Cache File" > "$UP_CACHE_FILE"

            HASUP=0
            UPCNT_SOLUS=0
            UPCNT_FP=0
            UPMSG_FP=""
            NOTI_LVL="normal"
            NOTI_ID=$(shuf -i 9000-11000 -n 1)

            # Make sure we are getting the latest
            pkcon refresh force &> /dev/null
            UPCNT_SOLUS=`pkcon get-updates --plain | grep -E -c "^(Security|Normal|Bugfix|Important)"`

            if [ "$2" == "force" ]; then
                echo -e "${CSS_CYANB}█ ${CSS_CYAN}${MSG_GEN_SYSTEM} (${SS_PKG_MGR})${CSS_RESET}\n${CSS_NBSP}${CSS_NBSP}${UPCNT_SOLUS} ${MSG_GEN_AVAILABLE}"
            fi
            if [ "$HAS_FLATPAK" -eq 1 ]; then
                #UPCNT_FP=`flatpak remote-ls --updates | wc -l`
                UPCNT_FP=$(flatpak remote-ls --updates --columns=application | grep -vFxf <(flatpak mask | awk '{print $1}') | wc -l)

                UPMSG_FP=" | $MSG_UPD_FLATPAK: $UPCNT_FP"

                if [ "$2" == "force" ]; then
                    echo ""
                    echo -e "${CSS_BLUEB}█ ${CSS_BLUE}${MSG_UPD_FLATPAK}${CSS_RESET}\n${CSS_NBSP}${CSS_NBSP}${UPCNT_FP} ${MSG_GEN_AVAILABLE}"
                fi
            else
                UPCNT_FP=0
            fi

            UPCNT_TTL=$((UPCNT_SOLUS + UPCNT_FP))

            if [ "$UPCNT_SOLUS" -gt 0 ]; then
                NOTI_LVL="critical"
                NOTI_ID=11111
            fi

            echo "TTL_UPDCNT=$UPCNT_TTL" >> "$UP_CACHE_FILE"
            echo "SOLUS_UPCNT=$UPCNT_SOLUS" >> "$UP_CACHE_FILE"
            echo "FLATPAK_UPCNT=$UPCNT_FP" >> "$UP_CACHE_FILE"

            if [ "$UPCNT_TTL" -gt 0 ]; then
                if [ "$UPCNT_TTL" -ne "$PREV_UPCNT_TTL" ] || [ ! -f "$UL_CACHE_FILE" ]; then
                    echo "$MSG_UPD_DISCO\n\n" > "$UL_CACHE_FILE"
                    if [ "$UPCNT_SOLUS" -gt 0 ]; then
                        echo "${CSS_BOLDBRIGHT}${CSS_CYAN}📦 Solus:${CSS_RESET}" >> "$UL_CACHE_FILE"
                        if [ "$SS_SOLUS_REPO" == "Unstable" ]; then
                            echo "${CSS_YELLOW}""$MSG_UPD_WARN""${CSS_RESET}\n" >> "$UL_CACHE_FILE"
                        fi
                        eopkg lu | awk -F' - ' '{print "\033[1;92m" $1 "\033[0m\n" $2"\n"}' >> "$UL_CACHE_FILE"
                    fi

                    if [ "$UPCNT_FP" -gt 0 ]; then
                        echo "${CSS_BOLDBRIGHT}${CSS_CYAN}📦 Flatpak:${CSS_RESET}" >> "$UL_CACHE_FILE"
                        flatpak remote-ls --updates --columns=application,name,version | grep -vFw -f <(flatpak mask | awk '{print $1}') | sed 's/^[^ \t]*[ \t]*//' >> "$UL_CACHE_FILE"
                        #flatpak remote-ls --updates --columns=name,version >> "$UL_CACHE_FILE"
                    fi
                fi
                if [ "$SS_NOTIFCATIONS" -eq 1 ] && [ "$1" == "system" ]; then
                    UPMSG="$MSG_UPD_SYSTEM: $UPCNT_SOLUS $UPMSG_FP"
                    notify-send --app-name="Solseek" --urgency="$NOTI_LVL" --replace-id=$NOTI_ID -t 9000 -i solseek "$MSG_UPD_AVAIL_UPD: $UPMSG"
                fi
            fi
        fi
        rm -f "$UP_LOCK_FILE"
    fi
}


fp_cache(){
    if [ "$HAS_FLATPAK" -eq 1 ]; then
        DOUPDATE=0
        rm -f "$UL_CACHE_FILE"

        if [ "$1" == "force" ] || [ ! -f "$FI_CACHE_FILE" ] || [ -n "$(find "$FI_CACHE_FILE" -mmin +"$SS_CACHE_EXPIRES" 2>/dev/null)" ]; then
            DOUPDATE=1
        fi

        if [ "$DOUPDATE" -eq 1 ]; then
            echo "$MSG_GEN_FCACHE"
            rm -f "$FI_CACHE_FILE"
            rm -f "$FA_CACHE_FILE"
            # This updates the appstream catalog for flatpaks
            solseek fpasc &

            flatpak list --app --columns=application,name |  sed -E 's/\x09(.*)/|\o33[32m⬤ \1\o33[0m/' |  sort -t '|' -k 2 > "$FI_CACHE_FILE"

            flatpak remote-ls --"$SS_FLATPAK_REPTYPE" flathub --columns=application,name | \
            awk '!seen[$1]++' | \
            grep -v 'org\.freedesktop\.Platform\.GL32\.nvidia\|org\.freedesktop\.Platform\.GL\.nvidia' | \
            sed -E 's/\t(.*)/|◯ \1/' | \
            sort -t '|' -k 2 > "$FA_CACHE_FILE"

            # If the user has no flatpaks installed, lets create an empty entry for FZF
            if [ ! -s "$FI_CACHE_FILE" ]; then
                #Create blank file so fzf works
                >"$FI_CACHE_FILE"
            else
                TMP_PGK_FILE=$(mktemp)

                awk -F'|' '

                FNR==NR {
                    # Store the entire line using the first field (Package ID) as the key
                    installed[$1] = $0
                    next
                }

                $1 in installed {
                    # Print the stored replacement line and skip to the next record
                    print installed[$1]
                    next
                }

                { print }
                ' "$FI_CACHE_FILE" "$FA_CACHE_FILE" > "$TMP_PGK_FILE" && mv "$TMP_PGK_FILE" "$FA_CACHE_FILE"

                rm -f "$TMP_PGK_FILE"
            fi
        fi
    fi

}


get_pkg_info(){
    if [ "$SS_PKG_MGR" == "eopkg" ]; then
        if [[ -n "$EPD_CACHE_FILE" ]]; then
            awk -v RS='\x1e' -v id="ID:$1\n" '
                index($0, id) == 1 {
                    print substr($0, length(id) + 1)
                    exit
                }
            ' "$EPD_CACHE_FILE"
        else
            ss_clean_of
            sleep 0.5 && eopkg info "$1" | awk 'NR==1{next} / :/{if(NR>2)print ""; sub(/\s+:\s*/, ":\n"); print; next} {sub(/^\s+/, ""); print} END{print ""}'
        fi

    else
      ## this will need refinement
        moss search "$1"
    fi
}

get_appstream_details(){
  appstreamcli get --details "$1" | awk '/^[^ ]/ { skip = ($0 ~ /^(Identifier|Internal ID|Icon|Bundle|Default Screenshot URL):/) } !skip'
}


eopkg_build_index(){
    echo "$MSG_GEN_PCACHE"
    eopkg la -N 2>/dev/null | awk 'NR>2 {print $1}' > "$IDX_CACHE_FILE"
}

eopkg_cache(){
    DOUPDATE=0
    rm -f "$UL_CACHE_FILE"
    LATESTHF=$(ls -t /var/lib/eopkg/history/*.xml 2>/dev/null | head -n 1)

    if [ "$1" == "force" ]; then
        DOUPDATE=1
    elif [ -f "$PA_CACHE_FILE" ] && [ -f "$PI_CACHE_FILE" ] && [ -f "$LATESTHF" ]; then
        LAST_OP_TIME=$(stat -c "%Y" "$LATESTHF")
        PA_CACHE_TIME=$(stat -c "%Y" "$PA_CACHE_FILE")

        if [ "$LAST_OP_TIME" -gt "$PA_CACHE_TIME" ]; then
            DOUPDATE=1
        fi
    else
        DOUPDATE=1
    fi

    if [ "$DOUPDATE" -eq 1 ]; then
        echo "$MSG_GEN_PCACHE"
        rm -f "$PI_CACHE_FILE"
        rm -f "$PA_CACHE_FILE"
        rm -f "$EPD_CACHE_FILE"
        rm -f "$RB_HISTORY_FILE"
        rm -f "$HISTORY_FILE"

        # Generate text based info db file
        if [[ -n "$SS_SOLUS_REPO_FILE" ]]; then
            $SS_DATA_PATH/helpers/eopkg-info.py "$SS_SOLUS_REPO_FILE" > "$EPD_CACHE_FILE" &
        fi

        TMP_PGK_FILE=$(mktemp)
        # Setup active Solus eopkg repo if using local cache. If the file is missing revert to online
        if [ "$SS_EOPKG_LCACHE" -eq 1 ]; then
            IDX_PATH="/var/lib/eopkg/index/$SS_SOLUS_REPO/eopkg-index.xml"

            if [ ! -f "$IDX_PATH" ]; then
                ## if we have the xz version cp it local, extract and use that
                if [ -f "$IDX_PATH.xz" ]; then
                    #TMP_IDX_FILE=$(mktemp)
                    cp -f "$IDX_PATH.xz" "$SS_CACHE_PATH"
                    unxz -f "$SS_CACHE_PATH/eopkg-index.xml.xz"
                    IDX_PATH="$SS_CACHE_PATH/eopkg-index.xml"
                else
                    SS_EOPKG_LCACHE=0
                    echo -e "$MSG_GEN_LCMISSING.\n"
                fi
            fi
        fi

        eopkg li 2>/dev/null | awk '{print $1 "|" "\033[32m⬤ " $1 "\033[0m"}' > "$PI_CACHE_FILE"

        if [ "$SS_EOPKG_LCACHE" -eq 1 ]; then
            awk -F'[<>]' '/<Package>/ {in_pkg=1} in_pkg && $2=="Name" && length($3)>0 {
            val=$3;
            gsub(/[[:cntrl:]]/, "", val);       # Remove invisible control chars (like \r)
            gsub(/^[[:space:]]+|[[:space:]]+$/, "", val); # Trim leading/trailing whitespace
            if (length(val) > 0) print val "|" "◯ " val;
            in_pkg=0
            }' "$IDX_PATH" | sort -u > "$PA_CACHE_FILE"

            awk -F'|' 'FNR==NR {seen[$1]; next} !($1 in seen)' "$PI_CACHE_FILE" $PA_CACHE_FILE > "$TMP_PGK_FILE"

        else
            eopkg la -U -N 2>/dev/null | awk 'NR>2 {print $1 "|" "◯ " $1 }' > "$TMP_PGK_FILE"
        fi

        cat "$PI_CACHE_FILE" "$TMP_PGK_FILE" | sort > "$PA_CACHE_FILE"

        rm -f "$TMP_PGK_FILE"
    fi

}

clean_cache(){
    if echo "$@" | grep -q "update"; then
        rm -f "$UP_CACHE_FILE"
        rm -f "$UL_CACHE_FILE"
    fi
    if echo "$@" | grep -q "regen";  then
        echo "$MSG_GEN_CACHE"
        rm -f "$UP_LOCK_FILE"
        check_updates "system" &
        fp_cache "force" &
        eopkg_cache
    fi
}


eopkg_rollback_menu(){
    LC_ALL=C eopkg history -l "$SS_ROLLBACK_LIMIT" | sed -nE 's/^(.*#([0-9]+)):.*/\2|\1/p'
}
eopkg_history_data(){

    if [ "$1" == "rollback" ]; then
        if [ "$1" == "force" ] || [ ! -f "$RB_HISTORY_FILE" ] || [ -n "$(find "$RB_HISTORY_FILE" -mmin +"$SS_CACHE_EXPIRES" 2>/dev/null)" ]; then
            eopkg history -l "${SS_ROLLBACK_LIMIT}" > "$RB_HISTORY_FILE";
        fi
        cat $RB_HISTORY_FILE 2>/dev/null
    else
        if [ "$1" == "force" ] || [ ! -f "$HISTORY_FILE" ] || [ -n "$(find "$HISTORY_FILE" -mmin +"$SS_CACHE_EXPIRES" 2>/dev/null)" ]; then
            eopkg history > "$HISTORY_FILE";
        fi
        cat $HISTORY_FILE 2>/dev/null
    fi
}

appstream_write_entry() {
    local type="${current_entry[type]}"
    local id="${current_entry[id]}"
    local name="${current_entry[name]}"
    local summary="${current_entry[summary]}"
    local pkg="${current_entry[pkg_name]}"

    statPre="◯"
    statEnd=""
    if [ -n "$summary" ]; then
        summary="- $summary"
    fi


    # Only write if we have a valid Name and Type
    if [[ -n "$name" && -n "$type" ]]; then
        if [[ "$type" == "flatpak" ]]; then
            # Format: flatpak:Identifier|Name - Summary
            if grep -Fq "$id" "$FI_CACHE_FILE"; then
                statPre="\033[32m⬤"
                statEnd="\033[0m"
            fi
            echo "flatpak:$id|$statPre [F] $name $summary $statEnd" >> "$AS_TMP_CACHE"
        elif [[ "$type" == "package" && -n "$pkg" ]]; then
            # Format: eopkg:Package|Name - Summary
            if grep -q "$pkg" "$PI_CACHE_FILE"; then
                statPre="\033[32m⬤"
                statEnd="\033[0m"
            fi
            echo "eopkg:$pkg|$statPre [P] $name $summary $statEnd" >> "$AS_TMP_CACHE"
        fi
    fi

    # Reset variables for the next block
    current_entry[type]=""
    current_entry[id]=""
    current_entry[name]=""
    current_entry[summary]=""
    current_entry[pkg_name]=""
}

appstream_get_list(){

    # Clear existing cache file
    > "$AS_TMP_CACHE"
    TMP_PGK_FILE=$(mktemp)

    #echo -e "$MSG_GEN_LOADCATALOG";
    if [ "$1" == "All" ]; then
        LC_ALL=C appstreamcli search . --no-color > "$TMP_PGK_FILE"
    else
        LC_ALL=C appstreamcli list-categories "$1" --no-color > "$TMP_PGK_FILE"
    fi


    INPUT_SOURCE="$TMP_PGK_FILE"

    declare -A current_entry

    # Initialize variables
    current_entry[type]=""
    current_entry[id]=""
    current_entry[name]=""
    current_entry[summary]=""
    current_entry[pkg_name]=""

    fpName=""

    while IFS= read -r line; do
        # Check for the separator "---" to process the block
        if [[ "$line" == "---" ]]; then
            appstream_write_entry
            continue
        fi

        # Extract Identifier (and clean [desktop-application])
        if [[ "$line" == Identifier:* ]]; then
            raw_id="${line#Identifier: }"
            # Remove ' [desktop-application]' and whitespace
            clean_id=$(echo "$raw_id" | sed 's/ \[desktop-application\]//g' | xargs)
            current_entry[id]="$clean_id"
        fi

        # Extract Name
        if [[ "$line" == Name:* ]]; then
            current_entry[name]="${line#Name: }$fpName"
        fi

        # Extract Summary
        if [[ "$line" == Summary:* ]]; then
            current_entry[summary]="${line#Summary: }"
        fi

        # Check for Bundle (indicating Flatpak)
        if [[ "$line" == Bundle:*flatpak* ]]; then
            current_entry[type]="flatpak"
        fi

        # Check for Package (indicating eopkg/native)
        if [[ "$line" == Package:* ]]; then
            current_entry[type]="package"
            current_entry[pkg_name]="${line#Package: }"
        fi

    done < "$INPUT_SOURCE"

    clear
    rm -f "$TMP_PGK_FILE"
}

# Get NVIDIA VGA compatible controller info
check_nvidia_support() {

  if [ "$1" == "check" ] || [ "$1" == "info" ]; then
      ALL_GPUS=$(lspci -nn | grep -i -E 'VGA|3D|Display')

      # First, check if an NVIDIA GPU is present
      if echo "$ALL_GPUS" | grep -q -i 'NVIDIA'; then
          # Extract the NVIDIA GPU name, removing the leading PCI bus ID
          SS_GPU=$(echo "$ALL_GPUS" | grep -i 'NVIDIA' | head -n 1 | sed -E 's/^.*: //')
          SS_GPU_NVIDIA=1
      else
          SS_GPU=""
      fi

      if [ "$SS_GPU_NVIDIA" -eq 1 ]; then

          # Check for Open Kernel Module Support
          # (GTX 16xx, RTX series, MX550/570, modern A-series/H-series workstations).
          if echo "$SS_GPU" | grep -q -i -E 'RTX|GTX 16[0-9][0-9]|MX5[57]0|A[0-9]0|H[0-9]0|T[0-9][0-9][0-9]|Quadro RTX'; then
              SS_NVIDIA_OPEN=1
          else
              SS_NVIDIA_OPEN=0
          fi

          # Detect installed 64-bit NVIDIA driver package
          NV_PKG=$(awk -F '|' '$1 ~ /^nvidia-(open|470-glx-driver|glx-driver|beta-driver|developer-driver)(-current)?$/ {print $1; exit}' "$PI_CACHE_FILE")


          if [ -n "$NV_PKG" ]; then
              SS_NVIDIA_INSTALLED="${NV_PKG}"
          fi

          #Detect installed 32-bit NVIDIA driver package ---
          NV32_PKG=$(awk -F '|' '$1 ~ /^nvidia.*32bit$/ {print $1; exit}' "$PI_CACHE_FILE" 2>/dev/null)

          if [ -n "$NV32_PKG" ]; then
            SS_NVIDIA32_INSTALLED="${NV32_PKG}"
          fi
      fi
      if [ "$1" == "info" ]; then
          if [ "$SS_GPU_NVIDIA" -eq 1 ]; then
              echo -e "${CSS_BOLDBRIGHT}${MSG_GEN_DETECTED} GPU:${CSS_RESET} ${SS_GPU}"
              hr "w30"
              echo -e "${CSS_BOLDBRIGHT}${MSG_GEN_DETECTED} ${MSG_GEN_DRIVERS}${CSS_RESET}"
              if [ -n "$SS_NVIDIA_INSTALLED" ]; then
                  echo -e "${CSS_GREEN}$SS_NVIDIA_INSTALLED${CSS_RESET}"
                  if [ -n "$SS_NVIDIA32_INSTALLED" ]; then
                      echo -e "${CSS_GREEN}32bit${CSS_RESET} ✅"
                  else
                      echo -e "${CSS_YELLOW}32bit${CSS_RESET} ❌"
                  fi
                  echo ""
                  nvidia-smi
              else
                  echo -e "${CSS_YELLOW}Nouveau${CSS_RESET}"
              fi
          else
               echo -e "${CSS_YELLOW}${MSG_GEN_UNSUPPORTED} GPU${CSS_RESET}"
          fi
      fi

  elif [ "$1" == "menu" ]; then
      MENUDA="$MENU_INVIDIA"
      if [ -n "$SS_NVIDIA_INSTALLED" ]; then
          MENUDA=$(echo "$MENUDA" | grep -v '^AMP_INST')
          if [ -n "$SS_NVIDIA32_INSTALLED" ]; then
              MENUDA=$(echo "$MENUDA" | grep -v '^AMP_ADD32|')
          else
              SS_NVMENU_MAP["AMP_ADD32"]="${SS_NVIDIA32_MAP[$SS_NVIDIA_INSTALLED]}"
          fi
          SS_NVMENU_MAP["AMP_REM"]="${SS_NVIDIA_INSTALLED} ${SS_NVIDIA32_INSTALLED}"
      else
          MENUDA=$(echo "$MENUDA" | grep -v '^AMP_REM|')
          MENUDA=$(echo "$MENUDA" | grep -v '^AMP_ADD32|')
          if [ "$SS_NVIDIA_OPEN" -eq 1 ]; then
              MENUDA=$(echo "$MENUDA" | grep -v '^AMP_INSTP')
              MENUDA=$(echo "$MENUDA" | grep -v '^AMP_INSTL')
          else
              MENUDA=$(echo "$MENUDA" | grep -v '^AMP_INSTO')
          fi
      fi

  fi

}
