#!/sbin/sh
##########################################################################################
#
# Unity Installer
# by ahrion & zackptg5
#
##########################################################################################

##########################################################################################
# PREP WORK
##########################################################################################

# PRELIMINARY DETECTION OF BOOTMODE
ps | grep zygote | grep -qv grep >/dev/null && BOOTMODE=true || BOOTMODE=false
$BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -qv grep >/dev/null && BOOTMODE=true

# TEMP INSTALLER PATH
TMPDIR=/dev/tmp
INSTALLER=$TMPDIR/install
MOUNTPATH=$TMPDIR/magisk_img

# OTHER VARIABLES
OUTFD=$2
ZIP=$3
MAGISK=true
DYNAMICOREO=false
DYNAMICAPP=false
SYSOVERRIDE=false
RAMDISK=false
DEBUG=false
case $(basename $ZIP) in
  *debug*|*Debug*|*DEBUG*) DEBUG=true;;
  *sysover*|*Sysover*|*SYSOVER*) SYSOVERRIDE=true;;
esac

# DEFAULT PERMISSIONS
umask 022

# INITIAL CLEANUP
rm -rf $TMPDIR 2>/dev/null
mkdir -p $INSTALLER

# GET OUTFD
if [ -z $OUTFD ] || readlink /proc/$$/fd/$OUTFD | grep -q /tmp; then
  # We will have to manually find out OUTFD
  for FD in `ls /proc/$$/fd`; do
    if readlink /proc/$$/fd/$FD | grep -q pipe; then
      if ps | grep -v grep | grep -q " 3 $FD "; then
        OUTFD=$FD
        break
      fi
    fi
  done
fi

# NEEDED BEFORE UTIL_FUNCTIONS IS LOADED
ui_print() {
  $BOOTMODE && echo "$1" || echo -e "ui_print $1\nui_print" >> /proc/self/fd/$OUTFD
}

##########################################################################################
# SETUP (UN)/INSTALL
##########################################################################################

# UNZIP FILES
ui_print " "
ui_print "Unzipping files..."
unzip -oq "$ZIP" -d $INSTALLER 2>/dev/null
[ ! -f $INSTALLER/config.sh ] && { ui_print "! Unable to extract zip file !"; exit 1; }

# LOAD FUNCTIONS
tar -xf $INSTALLER/common/unityfiles.tar.xz -C $INSTALLER/common 2>/dev/null
. $INSTALLER/common/unityfiles/util_functions.sh
setup_flashable

[ "$(grep_prop id $INSTALLER/module.prop)" == "UnityTemplate" ] && { ui_print "! Unity Template is not a separate module !"; abort "! This template is for devs only !"; }

# INSERT MODULE INFO INTO CONFIG.SH
(
for TMP in version name author; do
  NEW=$(grep_prop $TMP $INSTALLER/module.prop)
  [ "$TMP" == "author" ] && NEW="by ${NEW}"
  CHARS=$((${#NEW}-$(echo "$NEW" | tr -cd "©®™" | wc -m)))
  SPACES=""
  if [ $CHARS -le 41 ]; then
    for i in $(seq $(((41-$CHARS) / 2))); do
      SPACES="${SPACES} "
    done
  fi
  if [ $(((41-$CHARS) % 2)) == 1 ]; then sed -i "s/<$TMP>/$SPACES$NEW${SPACES} /" $INSTALLER/config.sh; else sed -i "s/<$TMP>/$SPACES$NEW$SPACES/" $INSTALLER/config.sh; fi
done
)

. $INSTALLER/config.sh

# PRINT MOD NAME
print_modname

# MOUNT DATA AND CACHE
ui_print "- Mounting /data, /cache"
is_mounted /data || mount /data || is_mounted /cache || mount /cache || { ui_print "! Unable to mount partitions"; exit 1; }

# INSTALL
unity_install() {
  ui_print " "
  ui_print "- Installing"

  # MAKE INFO FILE
  rm -f $INFO
  mktouch $INFO

  # RUN USER INSTALL SCRIPT
  [ -f "$INSTALLER/common/install.sh" ] && . $INSTALLER/common/install.sh

  # INSTALL SCRIPTS
  ui_print "   Installing scripts for $ROOTTYPE..."
  if $MAGISK; then
    # AUTO MOUNT
    $AUTOMOUNT && ! $SYSOVERRIDE && mktouch $MODPATH/auto_mount
    # UPDATE INFO FOR MAGISK MANAGER
    if $BOOTMODE; then
      mktouch /sbin/.core/img/$MODID/update
      cp_ch -n $INSTALLER/module.prop $MODPATH/module.prop
    fi
  elif [ "$ROOTTYPE" == "LineageOS SU" ] || [ "$ROOTTYPE" == "other root or rootless" ]; then
    ui_print " "
    ui_print "   ! This root method has no boot script support !"
    ui_print "   ! You will need to add init.d support !"
    ui_print " "
  fi
  if $MAGISK && $SYSOVERRIDE; then
    cp -f $INSTALLER/common/unityfiles/modidsysover.sh $INSTALLER/common/unityfiles/$MODID-sysover.sh
    sed -i -e "/# CUSTOM USER SCRIPT/ r $INSTALLER/common/uninstall.sh" -e '/# CUSTOM USER SCRIPT/d' $INSTALLER/common/unityfiles/$MODID-sysover.sh
    install_script -p $INSTALLER/common/unityfiles/$MODID-sysover.sh
  elif ! $MAGISK || $SYSOVERRIDE; then
    # INSTALL ROM BACKUP SCRIPT
    if [ -d /system/addon.d ]; then
      ui_print "   Installing addon.d backup script..."
      sed -i "s/<MODID>/$MODID/" $INSTALLER/common/unityfiles/addon.sh
      cp_ch -n $INSTALLER/common/unityfiles/addon.sh /system/addon.d/$MODID.sh 0755
    else
      ui_print "   ! Addon.d not detected. Backup script not installed..."
    fi
  fi

  # HANDLE REPLACE FOLDERS
  for TARGET in $REPLACE; do
    if $MAGISK; then mktouch $MODPATH$TARGET/.replace; else rm -rf $TARGET; fi
  done

  # PROP FILES - add prop function for system installs
  $PROPFILE && { prop_process $INSTALLER/common/system.prop; $MAGISK || echo $PROP >> $INFO; }

  # MODULE INFO
  cp_ch -n $INSTALLER/module.prop $MOD_VER

  #INSTALL POST-FS-DATA MODE SCRIPTS
  $POSTFSDATA && install_script -p $INSTALLER/common/post-fs-data.sh

  # SERVICE MODE SCRIPTS
  $LATESTARTSERVICE && install_script -l $INSTALLER/common/service.sh

  # INSTALL FILES
  ui_print "   Installing files for $ARCH SDK $API device..."
  rm -f $INSTALLER/system/placeholder $INSTALLER/ramdisk/placeholder
  $IS64BIT || rm -rf $INSTALLER/system/lib64 $INSTALLER/system/vendor/lib64
  for FILE in $(find $INSTALLER/system -type f 2>/dev/null | sed "s|$INSTALLER||" 2>/dev/null); do
    if $DYNAMICAPP; then
      if $OLDAPP; then FILE2=$(echo $FILE | sed 's|/system/app/.*/|/system/app/|'); else FILE2=$(echo $FILE | sed 's|/system/app/|/system/priv-app/|'); fi
    else
      FILE2=$FILE
    fi
    if $DYNAMICOREO && [ $API -ge 26 ]; then
      case $FILE in
        /system/lib*/modules/*) FILE2=$FILE;;
        /system/lib*/*) FILE2=$(echo $FILE | sed "s|/system/|$VEN/|");;
      esac
    fi
    cp_ch $INSTALLER$FILE $UNITY$FILE2
  done
  
  # ADD BLANK LINE TO END OF ALL PROP/SCRIPT FILES IF NOT ALREADY PRESENT
  for FILE in $MODPATH/*.sh $MODPATH/*.prop; do
    [ -f $FILE ] && { [ "$(tail -1 $FILE)" ] && echo "" >> $FILE; }
  done

  # REMOVE INFO FILE IF NOT NEEDED
  [ ! -s $INFO ] && rm -f $INFO
  
  # RAMDISK PATCHES
  if $RAMDISK; then
    [ -d "$RD" ] || unpack_ramdisk "late"
    # REMOVE RAMDISK MOD IF EXISTS
    if [ "$(grep "#$MODID-UnityIndicator" $RD/init.rc 2>/dev/null)" ]; then
      ui_print "   ! Mod detected in ramdisk!"
      ui_print "   ! Upgrading mod ramdisk modifications..."
      uninstall_files $INFORD
      sed -i "/#$MODID-UnityIndicator/d" $RD/init.rc
      [ -f "$INSTALLER/common/ramdiskuninstall.sh" ] && . $INSTALLER/common/ramdiskuninstall.sh
    fi
    # SCRIPT TO REMOVE MOD FROM SYSTEM/MAGISK IN EVENT MOD IS ONLY REMOVED FROM RAMDISK (LIKE DIRTY FLASHING)
    cp -f $INSTALLER/common/unityfiles/modidramdisk.sh $INSTALLER/common/unityfiles/$MODID-ramdisk.sh
    sed -i -e "/# CUSTOM USER SCRIPT/ r $INSTALLER/common/uninstall.sh" -e '/# CUSTOM USER SCRIPT/d' $INSTALLER/common/unityfiles/$MODID-ramdisk.sh
    install_script -p $INSTALLER/common/unityfiles/$MODID-ramdisk.sh
    # USE COMMENT AS INSTALL INDICATOR
    echo "#$MODID-UnityIndicator" >> $RD/init.rc
    [ -f "$INSTALLER/common/ramdiskinstall.sh" ] && . $INSTALLER/common/ramdiskinstall.sh
    for FILE in $(find $INSTALLER/ramdisk -type f 2>/dev/null | sed "s|$INSTALLER||" 2>/dev/null); do
      cp_ch $INSTALLER$FILE $INSTALLER/common/unityfiles/boot$FILE
    done
    [ ! -s $INFORD ] && rm -f $INFORD
  fi

  # SET PERMISSIONS
  ui_print " "
  ui_print "- Setting Permissions"
  set_permissions
}

# UNINSTALL
unity_uninstall() {
  ui_print " "
  ui_print "- Uninstalling"
  
  # REMOVE FILES
  uninstall_files $INFO

  $MAGISK && { rm -rf $MODPATH /sbin/.core/img/$MODID; rm -f $MOUNTPATH/.core/post-fs-data.d/$MODID-sysover.sh; }

  # RUN USER INSTALL SCRIPT
  [ -f "$INSTALLER/common/uninstall.sh" ] && . $INSTALLER/common/uninstall.sh
  
  # RAMDISK PATCHES
  if $RAMDISK; then
    [ -d "$RD" ] || unpack_ramdisk "late"
    uninstall_files $INFORD
    sed -i "/#$MODID-UnityIndicator/d" $RD/init.rc
    [ -f "$INSTALLER/common/ramdiskuninstall.sh" ] && . $INSTALLER/common/ramdiskuninstall.sh
  fi

  ui_print " "
  ui_print "- Completing uninstall -"
}

##########################################################################################
# (UN)INSTALL
##########################################################################################
# CHECK FOR OLD MAGISK, DETERMINE IF SYSTEM INSTALL OR MAGISK INSTALL, CHECK MAGISK VERSION (IF APPLICABLE)
MINMAGISK=$(grep_prop minMagisk $INSTALLER/module.prop)
if [ -f /data/adb/magisk/util_functions.sh ]; then
  MAGISKBIN=/data/adb/magisk
elif [ -f /data/magisk/util_functions.sh ]; then
  MAGISKBIN=/data/magisk
fi
if $BOOTMODE; then IMG=/data/adb/magisk_merge.img; else IMG=$(dirname $MAGISKBIN)/magisk.img; fi

if [ -z $MAGISKBIN ]; then
  MAGISK=false
  ui_print "- System install detected"
else
  ui_print "- Magisk install detected"
  cp -f $MAGISKBIN/util_functions.sh $INSTALLER/common/unityfiles/util_functions_mag.sh
  if $SYSOVERRIDE; then
    ui_print "- Overriding paths for system install"
    $BOOTMODE && { ui_print "   ! Magisk manager isn't supported!"; abort "   ! Install in recovery !"; }
    sed -i "s/-o ro/-o rw/g" $INSTALLER/common/unityfiles/util_functions_mag.sh
    sysover_partitions
  fi
  . $INSTALLER/common/unityfiles/util_functions_mag.sh
  [ ! -z $MAGISK_VER_CODE -a $MAGISK_VER_CODE -ge $MINMAGISK ] || require_new_magisk
fi

# MOUNT PARTITIONS AND DETECT VERSION/ARCHITECTURE
mount_partitions
api_level_arch_detect

if $MAGISK; then
  # SETUP BUSYBOX AND BINARIES
  $BOOTMODE && boot_actions_unity || recovery_actions
  # GET THE VARIABLE REQSIZEM
  request_zip_size_check "$ZIP"
  # THIS FUNCTION WILL MOUNT $IMG TO $MOUNTPATH, AND RESIZE THE IMAGE BASED ON $REQSIZEM
  mount_magisk_img
else
  # SETUP BUSYBOX AND BINARIES
  recovery_actions
fi

# CHECK FOR MIN & MAX API VERSION
[ -z $MINAPI ] || { [ $API -lt $MINAPI ] && require_new_api 'minimum'; }
[ -z $MAXAPI ] || { [ $API -gt $MAXAPI ] && require_new_api 'maximum'; }

# SET MODID and MODPATH variables
[ -z $MODID ] && MODID=`grep_prop id $INSTALLER/module.prop`
MODPATH=$MOUNTPATH/$MODID

# INSERT MODID AND CUSTOM USER SCRIPT INTO MOD SCRIPT
cp -f $INSTALLER/common/unityfiles/modid.sh $INSTALLER/common/unityfiles/post-fs-data.sh
cp -f $INSTALLER/common/unityfiles/modid.sh $INSTALLER/common/unityfiles/service.sh
sed -i -e "s/<MODID>/$MODID/" -e "/# CUSTOM USER SCRIPT/ r $INSTALLER/common/post-fs-data.sh" -e '/# CUSTOM USER SCRIPT/d' $INSTALLER/common/unityfiles/post-fs-data.sh
sed -i -e "s/<MODID>/$MODID/" -e "/# CUSTOM USER SCRIPT/ r $INSTALLER/common/service.sh" -e '/# CUSTOM USER SCRIPT/d' $INSTALLER/common/unityfiles/service.sh
mv -f $INSTALLER/common/unityfiles/post-fs-data.sh $INSTALLER/common/post-fs-data.sh
mv -f $INSTALLER/common/unityfiles/service.sh $INSTALLER/common/service.sh

# SET VARIABLES
set_vars

# ADD BLANK LINE TO END OF ALL COMMON FILES IF NOT ALREADY PRESENT
for FILE in $INSTALLER/common/*.sh $INSTALLER/common/*.prop; do
  [ "$(tail -1 $FILE)" ] && echo "" >> $FILE
done

# REMOVE OLD AML & MODS
[ -f "$OLD_AML_VER" ] && remove_old_aml

# UNPACK RAMDISK
$RAMDISK && unpack_ramdisk

#DEBUG
if $DEBUG; then
  ui_print " "
  ui_print "- Debug mode"
  ui_print "  Debug log will be written to: /sdcard/$MODID-debug.log"
  if $BOOTMODE; then exec 2>/storage/emulated/0/$MODID-debug.log; else exec 2>/data/media/0/$MODID-debug.log; fi
  set -x
fi

# LOAD USER VARS/FUNCTIONS
unity_custom

# UNPACK RAMDISK IF CHANGED TO TRUE IN UNITY_CUSTOM
$RAMDISK && [ ! -d "$RD" ] && unpack_ramdisk "late"

# DETERMINE MOD INSTALLATION STATUS
if $RAMDISK && [ "$(grep "#$MODID-UnityIndicator" $RD/init.rc 2>/dev/null)" ] && [ ! -f "$MOD_VER" ]; then
  ui_print " "
  ui_print "  ! Mod present in ramdisk but not in system!"
  ui_print "  ! Ramdisk modifications will be uninstalled!"
  rm -f $INSTALLER/common/uninstall.sh
  unity_uninstall
elif $MAGISK && ! $SYSOVERRIDE && [ -f "/system/addon.d/$MODID-files" -o -f "/system/etc/$MODID-files" ]; then
  ui_print " "
  ui_print "  ! Previous system override install detected!"
  ui_print "  ! Removing...!"
  $BOOTMODE && { ui_print "  ! Magisk manager isn't supported!"; abort "   ! Install in TWRP !"; }
  mount -o rw,remount /system
  [ -L /system/vendor ] && mount -o rw,remount /vendor
  sysover_partitions
  SYSOVERRIDE=true
  set_vars
  unity_uninstall
  SYSOVERRIDE=false
  set_vars
  unity_install
elif [ -f "$MOD_VER" ]; then
  if $RAMDISK && [ ! "$(grep "#$MODID-UnityIndicator" $RD/init.rc 2>/dev/null)" ]; then
    ui_print " "
    ui_print "  ! Mod present in system but not in ramdisk!"
    ui_print "  ! Running upgrade..."
    unity_uninstall
    unity_install
  elif [ $(grep_prop versionCode $MOD_VER) -ge $(grep_prop versionCode $INSTALLER/module.prop) ]; then
    ui_print " "
    ui_print "  ! Current or newer version detected!"
    unity_uninstall
  else
    ui_print " "
    ui_print "  ! Older version detected! Upgrading..."
    unity_uninstall
    unity_install
  fi
else
  unity_install
fi

# COMPLETE (UN)INSTALL
cleanup
