#!/system/bin/sh
MODDIR=${0%/*}

cd $MODDIR
export PATH="/system/bin:$MODDIR:$PATH"
echo "-17" > "/proc/$$/oom_adj"
echo "-1000" > "/proc/$$/oom_score_adj"

# 2023/09/25 风也吹不动
# 脚本可能还处于实验阶段，支持二改，完成度也算可以了
# 估计还有些不严谨的地方，但我可能没有什么精力维护了，能用就行，注释 我会尽量表达我的意图


## # # # # # ##
# count：模块装上后能允许加载的个数，不出意外是全部
# array：存放包名，next_index和index为array的下标，顺序索引切换
# 我的目的是能让缺少/新增动画也能正常运行 (部分用户可能会删掉模块内不喜欢的动画或新增)
## # # # # # ##



#### ↓能改动的地方↓ ####
# 包名(不是文件名)，后面不带数字，需要精确可以把所有包名列上去，必须空格隔开，也可换行(但换行必须引号最后一行括起来)
NAME='com.bs.bscharge com.redmagic.charge com.rog.charge'
BATTERY_STATUS_FILE="/sys/class/power_supply/battery/status"
conf_file="$MODDIR/config.conf"
log_file="$MODDIR/log.log"
# 是否随机切换？ 顺序=0  随机=1
rand=0
# 切换的方法：默认0(最兼容 没有问题就不用改)，如果第三方主题切换时候突然恢复官方主题可以尝试改成1，但不保证一定有效
is_exclusive=0
#### ↑能改动的地方↑ ####



# 简化下命令，太多你们可能看着比较乱
alias p='echo'
alias g='grep'
alias gi='grep -i'
alias co='cmd overlay'








# inotify会监控充电变化和config.conf的文件，要换成debug请直接修改config.conf文件，inotify会自杀，无需自行拔插充电器切换到轮询，但要换回inotify状态，还请麻烦拔插一下
# C语言源码在原模块zip文件内SourceCode
# 功耗很低，一天下来功耗比执行两三条简单的命令还要低
function inotify_func()
{
# 命令解释：F全缓冲，e事件：读取， -f被监听的文件，status_file log_file会自动创建
inotify -Fe ACCESS -s "$1" -f "$BATTERY_STATUS_FILE" \
--status_file="$conf_file" \
--log_file="$MODDIR/inotify.log"  2>&1
return $?
}


# 轮询模式
debug() {
# FuncName  file  str  cmd(opt)  %d/%f
    case "$3" in
        "sleep")
            while [[ `cat "$1"` != "$2" ]] ; do
                sleep $4
            done
            ;;
        "usleep")
            while [[ `cat "$1"` != "$2" ]] ; do
                usleep $4
            done
            ;;
    esac
    return 0
}


err() {
    [[ `cat $log_file  2>/dev/null` == "" ]] && p "******** 记录 ********" > $log_file
    p '' >> "$log_file"
    date "+%Y/%m/%d %T" | tee -a "$log_file"
    p "$1" | tee -a "$log_file"
    exit 1
}


# inotify报错处理，你无需关注这整块函数
function check_inotify()
{
    local status result target
    typeset -l result
    status=$1
    result="$2"
    target="$3"
    # 不管inotify退出什么状态，只要现在正确就过
    if [[ `cat $BATTERY_STATUS_FILE` == "$target" ]] ; then
        return 0
    fi

    case "$status" in
        "0")
            # 转成小写再比较，result已经变小写了
            typeset -l target
            target="$target"
            if [[ `printf %s "$result"` == "$target" ]] ; then
                check_ret='continue'
                return 1
            fi
            ;;
        "1")
            case "$result" in
                *inotify\ init*)
                    check_ret='false'
                    return 1
                    ;;
                *inotify\ watch*)
                    check_ret='false'
                    return 1
                    ;;
                *file\ read\ error*)
                    check_ret='false'
                    return 1
                    ;;
                *segment*)
                    if [[ `p "$result" | g 'segment' | g 'fault'` != "" ]] ; then
                        check_ret='false'
                        return 1
                    fi
                    ;;
                *out\ of\ memory*)
                    check_ret='continue'
                    return 1
                    ;;
                *killed*)
                    check_ret='continue'
                    return 1
                    ;;
            esac
            check_ret='false'
            return 1
            ;;
        *)
            case "$result" in
                *segment*)
                    if [[ `p "$result" | g 'segment' | g 'fault'` != "" ]] ; then
                        check_ret='false'
                        return 1
                    fi
                    ;;
                *out\ of\ memory*)
                    check_ret='continue'
                    return 1
                    ;;
                *killed*)
                    check_ret='continue'
                    return 1
                    ;;
            esac
            # inotify过不去 出错，不知道发生什么，但用循环就完事了
            check_ret='false'
            return 1
            ;;
    esac
}


function p_list()
{
    local s all_list
    all_list=`co list com.android.systemui`
    for s in $NAME
    do
        p "$all_list" | g $s
    done
}


function init()
{
    local i list str package packages
    count=0
    # 一般在systemui启动之前能捕捉到叠加层状态
    while [[ `co list com.android.systemui` == "" ]] ; do
        sleep 0.4
    done

    list=`p_list`
    packages=`p "$list" | awk '{print $NF}'`
    [[ "$list" == "" ]] && err "无法加载叠加层，原因未知"
    if [[ `printf %s "$packages" | awk 'END{print NR}'` == 1 ]] ; then
        co enable-exclusive $packages
        err "动画数量为1，暂不用切换"
    fi
    # 计算动画加载个数、存放包名数字
    for package in $packages; do
        array[$count]=`p "$package"`
        ((count++));
    done
    # 如果重启后已加载，index为当前启用的下标，next_index=index+1
    str=`status_num`
    if [ "$str" == "1" ]; then
        package=`p "$list" | gi 'x' | awk '{print $NF}'`
        for i in `seq 0 +1 $count` ; do
            if [[ "${array[i]}" == "$package" ]] ; then
                index=$i
                next_index=$(($index + 1))
                [[ "$i" == "$(($count - 1))" ]] && next_index=0
                break
            fi
        done
    else
        [[ "$str" == "error" ]] && err "该模块不适合当前系统"
        # 没有启用或启用多个，可能是初次刷入模块
        index=$count
        next_index=0
    fi
    # 不短路
    if [[ "$index" == "$next_index" || "$next_index" == "" || "$index" == "" ]] ; then
        index=0
        next_index=0
    fi
}

# 状态，输出当前启用的数量
function status_num()
{
    local i list
    list=`p_list`
    if [[ `p "$list" | g '\['` != "" ]] ; then
        i=`printf %s "$list" | gi 'x' | awk 'END{print NR}'`
        p "$i"
    else
        p "error"
    fi
}


# 产生随机数
function rand_func()
{
    local num
    if [ -f /data/adb/magisk/busybox ]; then
        num=`/data/adb/magisk/busybox shuf -i 0-$(($count - 1)) -n1`
        [ $? -eq 0 ] && p $num && return 0
        return 1
    else
        num=$(($RANDOM % $count))
        [ $? -eq 0 ] && p $num && return 0
        return 1
    fi
}

# 异常处理，杀掉ui
function check_reload()
{
    true
    reload() {
        co enable-exclusive ${array[next_index]}
        sleep 0.4
        killall com.android.systemui
    }
    # 莫名出现启用不止一个或未启用，重载ui初始化
    if [[ `status_num` != "1" ]] ; then
        # 一般不会相等
        if [[ "$next_index" == "$index" ]]; then
            next_index=0
            index=$count
            reload
        else
            reload
        fi
    fi
}

function main()
{
    test -r $BATTERY_STATUS_FILE || err "充电文件不可读"
##别看漏
    init

    while true; do
        if [[ "$is_exclusive" == "1" ]] ; then
            co enable-exclusive ${array[next_index]}
        else
            co disable ${array[index]} && co enable ${array[next_index]}
        fi
        check_reload
        # 随机切换
        if [[ "$rand" == "1" ]] ; then
            tmp_num=`rand_func  2>/dev/null`
            if [ $? -eq 0 ]; then
                # 如果随机数与当前状态不相同才赋值，否则什么都不做
                if [[ "$tmp_num" != "$index" ]] ; then
                    index=$next_index
                    next_index=$tmp_num
                fi
            else
                # 随机数产生失败，强制换回顺序
                rand=0
            fi
        else
            # 换完自增
            next_index=$(($next_index + 1))
            index=$(($index + 1))
            # 下标到尾(count-1)或超过, 从0开始
            [[ "$next_index" -ge "$count" ]] && next_index=0
            [[ "$index" -ge "$count" ]] && index=0
        fi


        # 监控充电状态，阻塞
        if [[ `cat "$conf_file" | g 'inotify'` == "status=inotify" ]] ; then
            while true ; do
                result=`inotify_func "Charging"`
                check_inotify "$?" "$result" "Charging"
                [ $? -eq 0 ] && break
                case "$check_ret" in
                    "false")
                        p "status=debug" > "$conf_file"
                        break
                        ;;
                    "continue")
                        # 尊重用户选择或inotify报错
                        [[ `g 'status=' "$conf_file" | g 'inotify'` == "status=inotify" ]] && continue
                        p "status=debug" > "$conf_file"
                        break
                        ;;
                esac
            done
        else
            # inotify要是没有问题尽量别用sleep+cat轮询，效率及功耗的问题，不过也不会特别明显
            p "status=debug" > "$conf_file"
            debug "$BATTERY_STATUS_FILE" "Charging" "sleep" "5"
        fi


        if [[ `cat "$conf_file" | g 'inotify'` == "status=inotify" ]] ; then
            while true ; do
                result=`inotify_func "Discharging"`
                check_inotify "$?" "$result" "Discharging"
                [ $? -eq 0 ] && break
                case "$check_ret" in
                    "false")
                        p "status=debug" > "$conf_file"
                        break
                        ;;
                    "continue")
                        # 尊重用户选择或inotify报错
                        [[ `g 'status=' "$conf_file" | g 'inotify'` == "status=inotify" ]] && continue
                        p "status=debug" > "$conf_file"
                        break
                        ;;
                esac
            done
        else
            # inotify要是没有问题尽量别用sleep+cat轮询，效率及功耗的问题，不过也不会特别明显
            p "status=debug" > "$conf_file"
            debug "$BATTERY_STATUS_FILE" "Discharging" "usleep" "3000000"
        fi
    done
}

### RUN ###
main
