#!/system/bin/sh
#h#
#h# uninstall_playstore_update.sh #VERSION# - uninstall a PlayStore update
#h#
#h# Usage: uninstall_playstore_update.sh  [-h|--help] [-H] [-d|--dryrun] [-x|--doit] [-f|--force] [-r|--reboot] [-v|--verbose] [-V|--version] [var=value]
#h#
#H# Known parameter:
#H# 
#H# -h               print the short usage help
#H# -H               print the detailed usage help
#H# -d               run the script in dry-run mode
#H# -x               delete the PlayStore update if the PlayStore is currently not running
#H# -f               delete the PlayStore update even if the PlayStore is currently running
#H# -r               reboot the phone after deleting the PlayStore update
#H# -v               print more messages
#H# -V               print the script version and exit
#H# var=value        set the variable "var" to the value "value"
#H#
#H# Return codes:
#H#
#H#   0 - no PlayStore update found
#H#   1 - PlayStore update found but not deleted
#H#   2 - PlayStore update deleted; reboot required
#H#   3 - PlayStore update found and the PlayStore is running
#H#   4 - no installed PlayStore found
#H#
#H# Set the variable PREFIX to "echo" or something similar to run the script in dry-run mode
#H# Set the environment variable TRACE to any value to run the script with "set -x"
#H#
#
#
# Lines beginning with #h# are printed if the script is executed with the parameter "-h" or "--help"
#
# Lines beginning with #H# are printed if the script is executed with the parameter "-H"
#
# Author
#   Bernd Schemmer (bernd dot schemmer at gmx dot de)
#
# History
#   06.09.2025 /bs v1.0.0
#     initial release
#

# ----------------------------------------------------------------------
# define constants
#

__TRUE=0
__FALSE=1

# ---------------------------------------------------------------------
# global variables
#

PLAYSTORE_APP="com.android.vending"

# Script return code
#
THISRC=0

# ----------------------------------------------------------------------
# enable tracing if requested
#
if [ "${TRACE}"x != ""x ] ; then
  set -x
elif [[ $- == *x* ]] ; then
#
# tracing is already enabled 
#
  TRACE=${__TRUE}
fi

# ----------------------------------------------------------------------
# enable verbose mode if requested
#

if [[ " $* " == *\ -v\ * || " $* " == *\ --verbose\ *  ]] ; then
  VERBOSE=${__TRUE}
fi

# ----------------------------------------------------------------------
# install a trap handler for house keeping
#
trap "cleanup"  0

# ----------------------------------------------------------------------
# read the script version from the source code
#
SCRIPT_VERSION="$( grep  "^#" $0 | grep "/bs v"  | tail -1 | sed "s#.*v#v#g" )"

# ---------------------------------------------------------------------
# aliase
#
alias LogInfoVar='f() { [[ ${__FUNCTION} = "" ]] && __FUNCTION=main ; [[ ${VERBOSE} != 0 ]] && return; varname="$1"; eval "echo \"INFO: in $__FUNCTION:  $varname ist \${$varname}\" >&2"; unset -f f; } ;  f'

# ---------------------------------------------------------------------
# functions

# ---------------------------------------------------------------------
# LogMsg - write a message to STDOUT
#
# Usage: LogMsg [message]
#
function LogMsg {
  typeset __FUNCTION="LogMsg"
  
  typeset THISMSG="$@"

  echo "${THISMSG}"

  return ${__TRUE}
}

# ---------------------------------------------------------------------
# LogInfo - write a message to STDERR if VERBOSE is ${__TRUE}
#
# Usage: LogInfo [message]
#
# The function  returns ${__TRUE} if the message was written and
# ${__FALSE} if the message was not written
#
function LogInfo { 
  typeset __FUNCTION="LogInfo"

  [[ ${VERBOSE} == ${__TRUE} ]] && LogMsg "INFO: $@" >&2 || return ${__FALSE}
}

# ---------------------------------------------------------------------
# LogWarning - write a warning message to STDERR
#
# Usage: LogWarning [message]
#
function LogWarning {
  typeset __FUNCTION="LogWarning"

  LogMsg "WARNING: $@" >&2
}


# ---------------------------------------------------------------------
# LogError - write an error message to STDERR
#
# Usage: LogError [message]
#
function LogError {
  typeset __FUNCTION="LogError"

  LogMsg "ERROR: $@" >&2
}


# ---------------------------------------------------------------------
# die - end the program
#
# Usage:
#  die [returncode] [message]
# 
# returns:
#   n/a
#
function die {
  typeset __FUNCTION="die"

  typeset THISRC="$1"

  [ "${THISRC}"x = ""x ] && THISRC=0

  [ $# -gt 0 ] && shift

  typeset THISMSG="$*"
  
  if [ ${THISRC} -le 4 ] ; then
    [ "${THISMSG}"x != ""x ] && LogMsg "${THISMSG} (RC=${THISRC})"
  else
    LogError "${THISMSG} (RC=${THISRC})"
  fi

  exit ${THISRC}
}


# ---------------------------------------------------------------------
# cleanup - house keeping at script end
#
# Usage:
#  cleanup
# 
# returns:
#   this function is used as trap handler to cleanup the environment
#
function cleanup {

  LogInfo "cleanup from $0 is running ..."

#
# remove the trap handler
#
  trap ""  0

  if [ "${PREFIX}"x != ""x ] ; then
    LogMsg ""
    LogMsg "*** The variable PREFIX is defined (PREFIX=\"${PREFIX}\") -- the script was executed in dry-run mode"
  fi

  LogMsg ""
  
# cleanup the environment 

}


# ----------------------------------------------------------------------
# install the trap handler
#
trap "cleanup" 0

# ----------------------------------------------------------------------
#
if [ "${PREFIX}"x != ""x ] ; then
# 
# check mksh (in some mksh versions PREFIX is used for a directory name)
#
  if [ -d "${PREFIX}" ] ; then
    LogWarning "The variable PREFIX contains a directory name: \"${PREFIX}\" -- disabling dry-run mode now (use the parameter \"-d\" to enable dry-run mode"
    PREFIX=""
  fi
fi

# ---------------------------------------------------------------------

# ---------------------------------------------------------------------
# main function


# ---------------------------------------------------------------------
# process the script parameter
#

LogInfo "Processing the parameter ..."

LogInfo "The parameter for the script are "  && \
  LogMsg "$*"


FORCE=${__FALSE}

REBOOT_PHONE=${__FALSE}

DOIT=${__FALSE}

PRINT_USAGE_HELP=${__FALSE}

PRINT_DETAILED_USAGE_HELP=${__FALSE}

while [ $# -ne 0 ] ; do
  CUR_PARAMETER="$1"
  shift

  LogInfo "Processing the parameter \"${CUR_PARAMETER}\" ..."

  case  ${CUR_PARAMETER} in
  
    -h | --help )
      PRINT_USAGE_HELP=${__TRUE}
      ;;

    -H )
      PRINT_USAGE_HELP=${__TRUE}
      PRINT_DETAILED_USAGE_HELP=${__TRUE}
      ;;
  
    -d | --dryrun )
      PREFIX="echo"
      ;;

    -f | --force )
      FORCE=${__TRUE}
      DOIT=${__TRUE}
      ;;

    -r | --reboot )
      REBOOT_PHONE=${__TRUE}
      ;;

    -x | --doit )
      DOIT=${__TRUE}
      ;;

    *=* )
      LogInfo "Executing now \"${CUR_PARAMETER}\" ..."
      eval ${CUR_PARAMETER}
      if [ $? -ne 0 ] ; then
        die 70 "Error executing \"${CUR_PARAMETER}\" "
      fi
      ;;

   -v | --verbose )
      VERBOSE=${__TRUE}
      ;;
       
   -V | --version )
      echo "${SCRIPT_VERSION}"
      die 0
      ;;

    --* | -* )
      die 17 "Unknown option found in the parameter: \"${CUR_PARAMETER}\")"
      ;;

    *  )
      die 19 "Unknown parameter found: \"${CUR_PARAMETER}\")"
      ;;

  esac
done


# ---------------------------------------------------------------------

if [ "${PREFIX}"x != ""x ] ; then
  LogMsg ""
  LogMsg "*** The script is running in dry-run mode: PREFIX is \"${PREFIX}\" "
  LogMsg ""
fi

# ---------------------------------------------------------------------

if [ ${PRINT_USAGE_HELP} = ${__TRUE} ] ; then
  grep "^#h#" $0 | cut -c4- | sed \
        -e "s/#VERSION#/${SCRIPT_VERSION}/g" 
  
  if [ ${PRINT_DETAILED_USAGE_HELP} = ${__TRUE} ] ;then
    grep "^#H#" $0 | cut -c4- 
  else
    echo " Use the parameter \"-H\" to print the detailed usage help"
  fi
              
  die 0
fi

# ---------------------------------------------------------------------
# check pre-requisites for the script
#
THIS_USER=$( id -un )

if [ "${THIS_USER}"x != "root"x ] ; then
  die 100 "This script needs root access rights (the current user is \"${THIS_USER}\")"
fi


# default: do not uninstall the update if the PlayStore is running
#
UNINSTALL_PLAYSTORE_UPDATE=${__FALSE}


# Find the installed PlayStore apk
# 
  CURRENT_PKG_DIR=$( pm path "${PLAYSTORE_APP}" | sed 's/package://;s/base.apk//' | head -1 )

  if [ -n "${CURRENT_PKG_DIR}" ] && [ -d "${CURRENT_PKG_DIR}" ]; then

    LogMsg "There is an update for the PlayStore installed in the directory \"${CURRENT_PKG_DIR}\":"
    LogMsg
    LIST_OF_NEW_FILES="$( find ${CURRENT_PKG_DIR} )"
    LogMsg "$( ls -ldZ ${LIST_OF_NEW_FILES} )"
    LogMsg

    LogMsg "Checking if the PlayStore is running ..."
    ps -ef | grep -v grep | grep "${PLAYSTORE_APP}$" 
    if [ $? -eq 0 ] ; then
      LogMsg "The PlayStore is running"

      if [ ${FORCE} != ${__TRUE} ] ; then
        UNINSTALL_PLAYSTORE_UPDATE=${__FALSE}
        LogMsg "Nothing to do right now (use the parameter \"-f\" or \"--force\" to uninstall the PlayStore update anyway "
        THISRC=3
      else
        LogMsg "Parameter \"-f\" found -- deleting the PlayStore update anyway"
        UNINSTALL_PLAYSTORE_UPDATE=${__TRUE}    
      fi
    else
      LogMsg "The PlayStore is not running - looks like the PlayStore update is not working "
      UNINSTALL_PLAYSTORE_UPDATE=${__TRUE}        
    fi

    if [ ${UNINSTALL_PLAYSTORE_UPDATE} = ${__TRUE} ] ; then
      if [ ${DOIT} = ${__TRUE} ] ; then
      
        LogMsg "Deleting the PlayStore update ..."
        
        ${PREFIX} pm uninstall --user 0 "${PLAYSTORE_APP}" 

        ${PREFIX} pm clear com.android.vending

        LogMsg "Deleting the files in \"${CURRENT_PKG_DIR}\" ..."
        
        ${PREFIX} rm -rf "${CURRENT_PKG_DIR}"/*

        LogMsg "Deleting the files in in the cache directories ..."

        ${PREFIX} rm -rf /data/system/package_cache/*/*vending* 

        ${PREFIX} rm -rf /data/system/package_cache/*/*FakeStore* 

        ${PREFIX} rm -rf  /data/data/com.android.vending
        
        LogMsg "Reinstalling the original version of the PlayStore ..."
        
        ${PREFIX} cmd package install-existing  "${PLAYSTORE_APP}"
        
        if [ ${REBOOT_PHONE} = ${__TRUE} ] ; then
          LogMsg "Rebooting the phone to activate the original PlayStore version ..."
          ${PREFIX} reboot
        else
          LogMsg "Reboot the phone to activate the original PlayStore (use the parameter \"-r\" or \"--reboot\" to automatically reboot after deleting the PlayStore update"
        fi
  
        THISRC=2
      else
        LogMsg "Use the parameter \"-x\" or \"--doit\" to delete the PlayStore update"  
        THISRC=1
      fi
    fi
  else
    LogMsg "No PlayStore update found (The current path to the PlayStore is \"${CURRENT_PKG_DIR}\" )"
    THISRC=4
  fi

  return ${THISRC}
