upd_msg(){
    TTL_UPDCNT=0
    SOLUS_UPCNT=0
    FLATPAK_UPCNT=0
    UPCNT_FP=0
    UPMSG="$MSG_UPD_AVAIL_UPD $MSG_UPD_NONE"

    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="$MSG_UPD_AVAIL_UPD $MSG_UPD_SYSTEM: $SOLUS_UPCNT $UPMSG_FP"
    fi

    echo -e "$UPMSG"
    hr

    if [ "$1" == "list" ] && [ "$TTL_UPDCNT" -gt 0 ]; then
        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=name,version | fold -s -w 70
              fi
        else
            UPLIST=$(<"$UL_CACHE_FILE")
            echo -e "$UPLIST" | fold -s -w 70
        fi
    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

          if [ "$2" == "force" ]; then
            echo -e "Checking..."
          fi
          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 [ "$HAS_FLATPAK" -eq 1 ]; then
              UPCNT_FP=`flatpak remote-ls --updates | wc -l`
              UPMSG_FP=" | $MSG_UPD_FLATPAK: $UPCNT_FP"
          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=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"

      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
        touch "$FI_CACHE_FILE"
        echo "Empty|Empty" > "$FI_CACHE_FILE"
        #If it does lets merge the installed entries with available as FP has no command for this
        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
    eopkg info "$1" | awk 'NR==1{next} / :/{if(NR>2)print ""; sub(/\s+:\s*/, ":\n"); print; next} {sub(/^\s+/, ""); print} END{print ""}'
  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"

    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 'NR>2 {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(){
    LLIMIT="$SS_HISTORY_LIMIT"
    if [ "$1" == "rollback" ]; then
        LLIMIT="$SS_ROLLBACK_LIMIT"
    fi
    eopkg history
}

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
              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
                  hr
                  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

}

