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

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

# DETECT WHETHER IN BOOT MODE
ps | grep zygote | grep -v grep >/dev/null && BOOTMODE=true || BOOTMODE=false
$BOOTMODE || ps -A 2>/dev/null | grep zygote | grep -v grep >/dev/null && BOOTMODE=true

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

# MAGISK PATHS
MAGISKBIN=/data/adb/magisk
MOUNTPATH=$TMPDIR/magisk_img
$BOOTMODE && IMG=/data/adb/magisk_merge.img

# OTHER VARIABLES
ZIP=$3
MAGISK=true
DYNAMICOREO=false

# DEFAULT PERMISSIONS
umask 022

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

# GET OUTFD
OUTFD=$2
readlink /proc/$$/fd/$OUTFD 2>/dev/null | grep /tmp >/dev/null
if [ "$?" -eq "0" ]; then
  OUTFD=0
  for FD in `ls /proc/$$/fd`; do
    readlink /proc/$$/fd/$FD 2>/dev/null | grep pipe >/dev/null
    if [ "$?" -eq "0" ]; then
    ps | grep " 3 $FD " | grep -v grep >/dev/null
    if [ "$?" -eq "0" ]; then
      OUTFD=$FD
      break
    fi
    fi
  done
fi

# NEED THIS LOADED BEFORE UTIL_FUNCTIONS
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 -o "$ZIP" -d $INSTALLER 2>/dev/null

[ ! -f $INSTALLER/config.sh ] && { ui_print "! Unable to extract zip file !"; exit 1; }

# LOAD FUNCTIONS
. $INSTALLER/common/unityfiles/util_functions.sh

[ "$(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; }

script_type() {
  supersuimg_mount
  SHEBANG="#!/system/bin/sh"; ROOTTYPE="other root or rootless"; MODPATH=/system/etc/init.d; SEINJECT=/sbin/sepolicy-inject
  if [ "$supersuimg" ] || [ -d /su ]; then
    SHEBANG="#!/su/bin/sush"; ROOTTYPE="systemless SuperSU"; MODPATH=/su/su.d; SEINJECT=supolicy
  elif [ -e "$(find /data /cache -name supersu_is_here | head -n1)" ]; then
    SHEBANG="#!/su/bin/sush"; ROOTTYPE="systemless SuperSU"
    MODPATH=$(dirname `find /data /cache -name supersu_is_here | head -n1`)/su.d
    SEINJECT=supolicy
  elif [ -d /system/su ] || [ -f /system/xbin/daemonsu ] || [ -f /system/xbin/sugote ]; then
    MODPATH=/system/su.d; SEINJECT=supolicy; ROOTTYPE="system SuperSU"
  elif [ -f /system/xbin/su ]; then
    if [ "$(grep "SuperSU" /system/xbin/su)" ]; then
      MODPATH=/system/su.d; ROOTTYPE="system SuperSU"; SEINJECT=supolicy
    else
      ROOTTYPE="LineageOS SU"
    fi
  fi
}

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

  # MAKE INFO FILE
  rm -f $INFO
  mktouch $INFO
    
  # RUN USER INSTALL SCRIPT
  . $INSTALLER/common/install.sh
  
  # INSTALL SCRIPTS
  if $MAGISK; then
    ui_print "   Installing scripts for MagiskSU..."
    # AUTO MOUNT
    $AUTOMOUNT && mktouch $MODPATH/auto_mount
    # UPDATE INFO FOR MAGISK MANAGER
    if $BOOTMODE; then
      mktouch /sbin/.core/img/$MODID/update
      cp_ch_nb $INSTALLER/module.prop $MODPATH/module.prop
    fi 
  else
    ui_print "   Installing scripts for $ROOTTYPE..."
    [ "$ROOTTYPE" == "LineageOS SU" -o "$ROOTTYPE" == "other root or rootless" ] && { ui_print " "; ui_print "   ! This root method has no boot script support !"; ui_print "   ! You will need to add init.d support !"; ui_print " "; }
    # 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_nb $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
  
  # MODULE INFO
  cp_ch_nb $INSTALLER/module.prop $MOD_VER
  
  #INSTALL POST-FS-DATA MODE SCRIPTS
  $POSTFSDATA && install_script $INSTALLER/common/post-fs-data.sh
  
  # SERVICE MODE SCRIPTS
  $LATESTARTSERVICE && install_script $INSTALLER/common/service.sh
   
  # INSTALL FILES
  ui_print "   Installing files for $ARCH SDK $API device..."
  rm -f $INSTALLER/system/placeholder
  $IS64BIT || rm -rf $INSTALLER/system/lib64 $INSTALLER/system/vendor/lib64
  for FILE in $(find $INSTALLER/system -type f | sed "s|$INSTALLER||"); do
    if $DYNAMICOREO && [ $API -ge 26 ]; then
      case $FILE in
        /system/app/*) if [ -d $VEN/app ]; then FILE2=$(echo $FILE | sed "s|/system/|$VEN/|"); else FILE2=$(echo $FILE | sed 's|/system/app/|/system/priv-app/|'); fi;;
        /system/lib*) FILE2=$(echo $FILE | sed "s|/system/|$VEN/|");;
        *) FILE2=$FILE;;
      esac
    else
      if $OLDAPP; then FILE2=$(echo $FILE | sed 's|/system/app/.*/|/system/app/|'); else FILE2=$(echo $FILE | sed 's|/system/app/|/system/priv-app/|'); fi
    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
  $MAGISK && [ ! -s $INFO ] && rm -f $INFO
  
  # SET PERMISSIONS
  ui_print " "
  ui_print "- Setting Permissions"
  set_permissions
}

# UNINSTALL
unity_uninstall() {
  ui_print " "
  ui_print "- Uninstalling"
  
  # REMOVE FILES
  FILE=$INFO
  $BOOTMODE && [ -f /sbin/.core/img/$MODID/$MODID-files ] && FILE=/sbin/.core/img/$MODID/$MODID-files
  if [ -f $FILE ]; then
    while read LINE; do
      if [ "$(echo -n $LINE | tail -c 4)" == ".bak" ]; then
        continue
      elif [ -f "$LINE.bak" ]; then
        mv -f $LINE.bak $LINE
      else
        rm -f $LINE
        [ "$(ls $(dirname $LINE))" ] || rm -rf $(dirname $LINE)
      fi
    done < $FILE
    rm -f $FILE
  else
    $MAGISK || abort "   ! Mod not detected !"
  fi
  
  $MAGISK && rm -rf $MODPATH /sbin/.core/img/$MODID
  
  # RUN USER INSTALL SCRIPT
  . $INSTALLER/common/uninstall.sh
  
  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 [ ! -d $MAGISKBIN ] && [ ! -d /data/magisk ]; then
  MAGISK=false
  ui_print "- System install detected"
elif [ ! -f $MAGISKBIN/util_functions.sh ]; then
  require_new_magisk
else
  . $MAGISKBIN/util_functions.sh
  [ ! -z $MAGISK_VER_CODE -a $MAGISK_VER_CODE -ge $MINMAGISK ] || require_new_magisk
  ui_print "- Magisk install detected"
fi

# MOUNT PARTITIONS AND DETECT VERSION/ARCHITECTURE
mount_partitions
api_level_arch_detect

if $MAGISK; then
  # SETUP BUSYBOX AND BINARIES
  $BOOTMODE && boot_actions || 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
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

# UNIVERSAL VARIABLES
SYS=/system
INFO="$MODPATH/$MODID-files"
if [ -d /system/priv-app ]; then OLDAPP=false; else OLDAPP=true; fi

# SET MAGISK/SYSTEM SPECIFIC VARIABLES
if $MAGISK; then
  VEN=/system/vendor
  UNITY="$MODPATH"
  PROP=$MODPATH/system.prop
  if $BOOTMODE; then
    MOD_VER="/sbin/.core/img/$MODID/module.prop"
    OLD_AML_VER="/sbin/.core/img/audmodlib/module.prop"
  else
    MOD_VER="$MODPATH/module.prop"
    OLD_AML_VER="$MOUNTPATH/audmodlib/module.prop"
  fi
else
  # DETERMINE SYSTEM BOOT SCRIPT TYPE
  script_type
  UNITY=""
  MOD_VER="/system/etc/$MODID-module.prop"
  OLD_AML_VER="/system/etc/audmodlib-module.prop"
  PROP=$MODPATH/$MODID-props.sh
  if [ -d /system/addon.d ]; then
    INFO=/system/addon.d/$MODID-files
  else
    INFO=/system/etc/$MODID-files
  fi
fi

# USE VENDOR IF OREO OR NEWER
if $DYNAMICOREO && [ $API -ge 26 ]; then 
  LIBPATCH="\/vendor"; LIBDIR=$VEN;
else 
  LIBPATCH="\/system"; LIBDIR=/system;
fi

# 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

# LOAD USER VARS/FUNCTIONS
unity_custom

# DETERMINE MOD INSTALLATION STATUS
if [ -f "$MOD_VER" ]; then
  if [ $(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
