#!/system/bin/sh
# Terminal Magisk Mod Template
# by veez21 @ xda-developers
# Slimmed down for use as an app backend by @Skittles9823

# Module ID
ID="quickswitch"

# Mod Directory
MODDIR=${0%/*}

KSU=true    # removed during install if false
APATCH=true # removed during install if false

if [ "$KSU" ]; then
  BBDIR="/data/adb/ksu/bin/busybox"
elif [ "$APATCH" ]; then
  BBDIR="/data/adb/ap/bin/busybox"
  APATCH_VER=$(cat /data/adb/ap/version)
else
  BBDIR="/data/adb/magisk/busybox"
fi

cd $MODDIR

# Set Log Files
mkdir -p $MODDIR/logs
# > Verbose output goes here
VERLOG=$MODDIR/logs/$ID-verbose.log
oldVERLOG=$MODDIR/logs/$ID-verbose-old.log

# Start Logging verbosely
mv -f $VERLOG $oldVERLOG 2>/dev/null
mv -f $LOG $oldLOG 2>/dev/null
set -x 2>$VERLOG

########
# Main #
########
API=$(getprop ro.build.version.sdk)
PATH="$BBDIR:/sbin/:$PATH"
alias aapt2='$MODDIR/aapt2'
alias sign='$MODDIR/zipsigner'
OVERLAYDIR=$MODDIR/overlays
RAND=$(echo $RANDOM | sed -r 's|^(...).*|\1|')
DID_MOUNT_RW=
defaultlauncherPackage=$(aapt2 d strings /system/framework/framework-res.apk | grep -m 1 "com.android.quickstep.RecentsActivity" | awk '{ print $3 }' | sed "s|/.*||")
defaultlauncherPath=$(grep -m1 -E "$defaultlauncherPackage.*codePath.*app" /data/system/packages.xml | sed -r "s/.*codePath=(.*)/\1/; s/\"//g" | awk '{ print $1 }')
if [ ! $(echo $defaultlauncherPath | grep "/system/") ]; then
  defaultlauncherPath="/system${defaultlauncherPath}"
fi

abort() {
  echo "qsError: $1"
  echo "$1" >&2
}

abortexit() {
  echo "qsError: $1"
  echo "$1" >&2
  get_logs
  exit 1
}

# Functions to check if dirs is mounted
is_mounted() {
  grep " $(readlink -f $1) " /proc/mounts 2>/dev/null
  return $?
}

is_mounted_rw() {
  grep " $(readlink -f $1) " /proc/mounts | grep " rw," 2>/dev/null
  return $?
}

mount_rw() {
  mount -o remount,rw $1
  DID_MOUNT_RW=$1
}

unmount_rw() {
  if [ "x$DID_MOUNT_RW" = "x$1" ]; then
    mount -o remount,ro $1
  fi
}

set_perms() {
  echo "\nSetting permissions..."
  chmod 644 $STEPDIR/*
  chown 0:2000 $STEPDIR
  if [ ! "$1" == "com.android.systemui" ]; then
    chmod 755 $MODDIR/system/etc/
    chmod 644 $PERMISSIONXMLDIR/*
    chmod 644 $WHITELISTXMLDIR/*
    chmod 755 $SYSTEMIZE_TARGET/*
    chmod 644 $SYSTEMIZE_TARGET/*/*
  fi
}

get_logs() {
  echo "$(cmd overlay dump)" >$MODDIR/logs/$ID-overlays.log
  echo "---Device Info---" >$MODDIR/logs/$ID-vars.log
  grep "^ro.product.device[^#]" /system/build.prop |
    sed 's/ro.product.device/DeviceCode/g' >>$MODDIR/logs/$ID-vars.log
  grep "^ro.product.model[^#]" /system/build.prop |
    sed 's/ro.product.model/DeviceName/g' >>$MODDIR/logs/$ID-vars.log
  grep "^ro.build.type[^#]" /system/build.prop |
    sed 's/ro.build.type/BuildType/g' >>$MODDIR/logs/$ID-vars.log
  grep "^ro.build.version.security_patch[^#]" /system/build.prop |
    sed 's/ro.build.version.security_patch/SecurityPatch/g' \
      >>$MODDIR/logs/$ID-vars.log
  grep "^ro.product.cpu.abilist[^#]" /system/build.prop |
    sed 's/ro.product.cpu.abilist/Arch/g' >>$MODDIR/logs/$ID-vars.log
  grep "^ro.build.version.sdk[^#]" /system/build.prop |
    sed 's/ro.build.version.sdk/APIVer/g' >>$MODDIR/logs/$ID-vars.log
  grep "^ro.build.flavor[^#]" /system/build.prop |
    sed 's/ro.build.flavor/BuildFlavor/g' >>$MODDIR/logs/$ID-vars.log
  echo "\n---ROM Info---" >>$MODDIR/logs/$ID-vars.log
  grep "^ro.build.host[^#]" /system/build.prop |
    sed 's/ro.build.host/Host/g' >>$MODDIR/logs/$ID-vars.log
  grep "^ro.*.device[^#]" /system/build.prop >>$MODDIR/logs/$ID-vars.log
  echo -e "\n---Variables---" >>$MODDIR/logs/$ID-vars.log
  (
    set -o posix
    set
  ) >>$MODDIR/logs/$ID-vars.log
  if [ -z "$KSU" ] && [ -z "$APATCH" ]; then
    echo -e "\n---Magisk Version---" >>$MODDIR/logs/$ID-vars.log
    echo $(grep "MAGISK_VER_CODE=" /data/adb/magisk/util_functions.sh |
      sed "s/MAGISK_VER_CODE/MagiskVersion/") >>$MODDIR/logs/$ID-vars.log
  elif [ "$APATCH" ]; then
    echo -e "\n---APATCH Version---\nAPVersion=$APATCH_VER" >>$MODDIR/logs/$ID-vars.log
  else
    echo -e "\n---KSU Version---\nKSUVersion=$KSU_VER" >>$MODDIR/logs/$ID-vars.log
  fi
  echo -e "\n---Module Version---" >>$MODDIR/logs/$ID-vars.log
  echo $(grep "versionCode=" $MODDIR/module.prop) >>$MODDIR/logs/$ID-vars.log
  find $MODDIR >$MODDIR/logs/find.log

  rm -rf /storage/emulated/0/Documents/$ID/*
  mkdir -p /storage/emulated/0/Documents/$ID
  cp -rf $MODDIR/logs/* /storage/emulated/0/Documents/$ID/
  echo "\nLogs copied to /sdcard/Documents/$ID..."
}

setvars() {
  if [ -n "$KSU" ] || [ -n "$APATCH" ]; then
    STEPDIRPREFIX=$MODDIR
  else
    STEPDIRPREFIX=$MODDIR/system
  fi
  SUFFIX="/overlay/QuickSwitchOverlay"
  if [ "$API" -ge 29 ]; then
    STEPDIR=$STEPDIRPREFIX/product$SUFFIX
    case "$(getprop ro.product.brand) $(getprop ro.product.manufacturer)" in
    *samsung*)
      if [ ! -d /product/overlay ]; then
        STEPDIR=$STEPDIRPREFIX/vendor$SUFFIX
      fi
      ;;
    *OnePlus*)
      if [ "$API" -ge 31 ]; then
        if [ -d /system_ext/oplus ]; then
          STEPDIR=$STEPDIRPREFIX/vendor$SUFFIX
        else
          STEPDIR=$STEPDIRPREFIX/product$SUFFIX
        fi
      fi
      ;;
    *)
      PRODUCT=true
      if [ -z "$KSU" ] && [ -z "$APATCH" ]; then
        # Yay, magisk supports bind mounting /product now
        MAGISK_VER_CODE=$(grep "MAGISK_VER_CODE=" /data/adb/magisk/util_functions.sh | awk -F = '{ print $2 }')
        if [ $MAGISK_VER_CODE -ge "20000" ]; then
          STEPDIR=$STEPDIRPREFIX/product$SUFFIX
        else
          abort "Magisk v20 is required for users on Android 10"
          abortexit "Please update Magisk and try again."
        fi
      else
        STEPDIR=$STEPDIRPREFIX/product$SUFFIX
      fi
      ;;
    esac
  else
    SUFFIX="/overlay"
    if [ -d /oem/OP -o -d /OP ]; then
      case "$(getprop ro.product.manufacturer)" in
      LGE)
        OEM=true
        mkdir -p $MODDIR/$defaultlauncherPath
        touch $MODDIR/$defaultlauncherPath/.replace
        if [ -d /oem/OP ]; then
          STEPDIR=/oem/OP/OPEN_*/overlay/framework
          is_mounted " /oem" || mount /oem
          is_mounted_rw " /oem" || mount_rw /oem
          is_mounted " /oem/OP" || mount /oem/OP
          is_mounted_rw " /oem/OP" || mount_rw /oem/OP
        elif [ -d /OP ]; then
          STEPDIR=/OP/OPEN_*/overlay/framework
          is_mounted " /OP" || mount /OP
          is_mounted_rw " /OP" || mount_rw /OP
        fi
        # globs don't like to be quoted so we have to set the variable again without quotes first.
        STEPDIR=$STEPDIR
        ;;
      esac
    else
      PRODUCT=
      OEM=
      STEPDIR=$STEPDIRPREFIX/vendor$SUFFIX
    fi
  fi

  # Assign misc variables
  PERMISSIONXMLDIR=$MODDIR/system/etc/permissions
  WHITELISTXMLDIR=$MODDIR/system/etc/sysconfig
  SYSTEMIZE_TARGET=$MODDIR/system/priv-app
}

reset_provider() {
  setvars
  if [ "$OEM" ]; then
    rm -rf $STEPDIR/QuickSwitchOverlay.apk
  fi
  rm -rf $MODDIR/system
  if [ "$KSU" ] || [ "$APATCH" ]; then
    [ -d $MODDIR/product ] && rm -rf $MODDIR/product
    [ -d $MODDIR/vendor ] && rm -rf $MODDIR/vendor
  fi
  rm -rf /data/resource-cache/overlays.list
  find /data/resource-cache/ -name "*QuickstepSwitcherOverlay*" -exec rm -rf {} \;
  find /data/resource-cache/ -name "*QuickSwitchOverlay*" -exec rm -rf {} \;
}

unmount_rw_stepdir() {
  if [ "$OEM" ]; then
    is_mounted_rw " /oem" && unmount_rw /oem
    is_mounted_rw " /oem/OP" && unmount_rw /oem/OP
    is_mounted_rw " /OP" && unmount_rw /OP
  fi
}

switch_providers() {
  reset_provider

  echo "\nThe overlay will be copied to $STEPDIR..."

  if [ "$KSU" ] || [ "$APATCH" ]; then
    APKPATH=$(pm path $1 | sed "s|package:||")
  fi

  # Create needed dirs
  while [ ! -d "$STEPDIR" ]; do
    setvars
    mkdir -p $STEPDIR
  done

  if [ ! "$1" == "com.android.systemui" ]; then
    mkdir -p $SYSTEMIZE_TARGET/QuickSwitch-${1}-${RAND}
    mkdir -p $MODDIR/system/etc/permissions
    mkdir -p $MODDIR/system/etc/sysconfig
    if [ ! -z "$DATAAPKPATH" ]; then
      # if this yeets /data/app this time then its @paphonb's fault xdd
      rm -rf $DATAAPKPATH
    fi
    if [ ! -z "$REPLACEPATH" ]; then
      mkdir -p ${MODDIR}${REPLACEPATH}/
      touch ${MODDIR}${REPLACEPATH}/.replace
    fi
    cp -rf $APKPATH \
      $SYSTEMIZE_TARGET/QuickSwitch-"${1}"-"${RAND}"/QuickSwitch-"${1}"-"${RAND}".apk

    perms=$(aapt2 d permissions $APKPATH | grep "uses-permission:" |
      sed -r "s|.*='(.*)'|\1|")
    permissions=$(echo "$perms" |
      sed -re "s|  ||g; s|^|        <permission name=\"|; s|$|\"/>|")

    echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<permissions>
    <privapp-permissions package=\"${1}\">
$permissions
    </privapp-permissions>
</permissions>" >$PERMISSIONXMLDIR/privapp-permissions-$1.xml

    echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<config>
    <hidden-api-whitelisted-app package=\"${1}\"/>
</config>" >$WHITELISTXMLDIR/$1-hiddenapi-package-whitelist.xml

    # Get logs for the patching process if the selected launcher is OnePlus Launcher
    # If more launchers get patch functionality I'll make the package name a variable array which can easily be added to.
    if [ "$1" == "net.oneplus.launcher" ]; then
      echo $(logcat -d | grep "I Patcher") >$MODDIR/logs/$ID-Patcher.log
    elif [ -f "$MODDIR/logs/$ID-Patcher.log" ]; then
      rm $MODDIR/logs/$ID-Patcher.log
    fi
  fi

  echo "<?xml version=\"1.0\" encoding=\"utf-8\"?>
<resources>
	<string name=\"config_recentsComponentName\">$1/com.android.quickstep.RecentsActivity</string>
</resources>" >$OVERLAYDIR/overlay/values/strings.xml

  if [ ! -z "$PLATFORMSIGNATURE" ]; then
    cat "$PLATFORMSIGNATURE" >$OVERLAYDIR/overlay/values/arrays.xml
  fi

  rm -rf ${MODDIR}/compiled
  mkdir ${MODDIR}/compiled
  aapt2 compile -v --dir ${OVERLAYDIR}/overlay/ -o ${MODDIR}/compiled && \
    aapt2 link -o ${MODDIR}/unsigned.apk -I /system/framework/framework-res.apk \
      --manifest ${OVERLAYDIR}/AndroidManifest.xml ${MODDIR}/compiled/* \
      &>$MODDIR/logs/aapt2.log
  rm -rf ${MODDIR}/compiled

  if [ -s ${MODDIR}/unsigned.apk ]; then
    sign ${MODDIR}/unsigned.apk ${MODDIR}/signed.apk
    cp -rf ${MODDIR}/signed.apk ${STEPDIR}/QuickSwitchOverlay.apk
    [ ! -s ${MODDIR}/signed.apk ] && cp -rf ${MODDIR}/unsigned.apk ${STEPDIR}/QuickSwitchOverlay.apk
    rm -rf ${MODDIR}/signed.apk ${MODDIR}/unsigned.apk
  else
    abort "Overlay not created!"
    abort "This is generally a rom incompatibility,"
    abortexit "currently I'm unsure how to fix this."
  fi

  if [ -s ${STEPDIR}/QuickSwitchOverlay.apk ]; then
    echo "\nOverlay successfully copied..."
  else
    abortexit "The overlay was not copied, please send logs to the developer."
  fi

  set_perms $1

  # Lets save this for a rainy day
  #  SDK=$(getprop ro.build.version.sdk)
  #  SAMMY=$(getprop ro.product.brand)

  #  if [[ "$SDK" = 29 ]] && \
  #     [[ "$SAMMY" == *"samsung"* ]]; then
  #    for i in $(cmd overlay list | grep navbar | awk '{print $NF}' | \
  #        egrep -v com.samsung.internal.systemui.navbar.gestural_no_hint); do
  #      cmd overlay disable $i
  #    done
  #    cmd overlay enable com.samsung.internal.systemui.navbar.gestural_no_hint
  #  fi

  # lets not add this just yet as it can cause crashes in certain circumstances
  #  if [ ! "$1" == "com.android.systemui" ]; then
  #    echo "pm set-home-activity $1" > $MODDIR/service.sh
  #    echo 'rm -rf $0' >> $MODDIR/service.sh
  #  fi
}

print_modname() {
  # @Skittles9823 made this ascii and is way to proud of it
  echo " "
  echo "       _____       "
  echo "   __ |     | __   "
  echo "  |  ||     ||  |  "
  echo "  |  ||     ||  |  "
  echo "  |__||     ||__|  "
  echo "      |_____|      "
  echo "    QuickSwitch    "
  echo "                   "
  echo " The Lawnchair Team"
  echo " "
}

print_modname

resetprop ro.recents.grid false
sed -i "/ro.recents.grid*/d" $MODDIR/system.prop

for arg in $(echo ${@}); do
  args=$(echo $arg | tr '=' ' ')
  opt1=$(echo $args | awk '{ print $1 }')
  opt2=$(echo $args | awk '{ print $2 }')
  case "$opt1" in
  --reset)
    reset_provider
    echo "The recents provider has been reset to default."
    continue
    ;;
  --uninstall)
    reset_provider
    continue
    ;;
  --grid)
    resetprop ro.recents.grid true
    echo "ro.recents.grid=true" >>$MODDIR/system.prop
    continue
    ;;
  --ch)
    switch_providers "$opt2"
    continue
    ;;
  esac
done

# If the script is called, then there is no reason for the module to be disabled.
# Let's make sure the module is enabled.
rm -rf $MODDIR/disable

unmount_rw_stepdir

get_logs

echo "\nPlease reboot for changes to take effect."

exit $?
