#!/usr/bin/env bash
# =========================================================
# LEDE 自动更新 + feeds 清理 + 编译脚本
# 适用于:
# https://github.com/coolsnowwolf/lede
# 11 23 */3 * * /usr/bin/env bash /home/hailey/shell/lede.sh >> /home/hailey/shell/cron.log 2>&1
# luci-app-*:
# adguardhome argon-config arpbind autoreboot ddns firewall frpc
# ksmbd mosdns nlbwmon oaf package-manager passwall 
# syncthing tailscale-community ttyd 
# upnp vlmcsd vsftpd wol zerotier
# =========================================================

set -eo pipefail

# ================= 配置区域 =================

LEDE_DIR="/home/hailey/lede"
LOG_FILE="/home/hailey/shell/lede.log"
BUILD_DIRS=("bin" "build_dir" "dl" "feeds" "staging_dir" "tmp")

JOBS="$(nproc)"

DEEP_CLEAN=false

# ================= 日志 =================

log() {
    echo "[$(date '+%F %T')] $*" | tee -a "$LOG_FILE"
}

# ================= 检查 =================

check_env() {

    [[ -d "$LEDE_DIR" ]] || {
        log "LEDE 目录不存在: $LEDE_DIR"
        exit 1
    }

    cd "$LEDE_DIR" || exit 1

    [[ -f "Makefile" ]] || {
        log "不是 LEDE 源码目录"
        exit 1
    }
}

# ================= retry =================

retry() {

    local max=5
    local delay=10
    local count=1

    until "$@"; do

        if [[ $count -ge $max ]]; then
            log "命令执行失败: $*"
            return 1
        fi

        log "失败，${delay}s 后重试 (${count}/${max})"

        sleep "$delay"

        count=$((count + 1))
    done
}

# ================= 清理 =================

clean_build() {

    check_env

    log "开始清理..."

    make clean || true

    if [[ "$DEEP_CLEAN" == "true" ]]; then

        log "执行深度清理..."

        make dirclean || true
        for dir in "${BUILD_DIRS[@]}"; do
            target="$LEDE_DIR/$dir"
            if [ -d "$target" ]; then
                log "删除目录: $target"
                rm -rf "$target"
            else
                log "目录不存在, 跳过: $target"
            fi
        done
        
        log "深度清理完成"
    fi

    log "清理完成"
}

# ================= 更新源码 =================

update_source() {

    check_env

    log "更新源码..."

    git reset --hard HEAD
    git clean -fd

    retry git pull --rebase
}

# ================= 更新 feeds =================

update_feeds() {

    check_env
    # ===================================================== 
    # 1> feeds.conf.default 
    # ===================================================== 
    
    log "更新 feeds.conf.default..." 
    # sed -i '/passwall_packages/d' feeds.conf.default
    sed -i '/luci/d' feeds.conf.default 
    # sed -i '1i src-git kenzo https://github.com/kenzok8/openwrt-packages' feeds.conf.default 
    # sed -i '2i src-git small https://github.com/kenzok8/small' feeds.conf.default 
    # sed -i '1i src-git passwall_packages https://github.com/Openwrt-Passwall/openwrt-passwall-packages.git;main' feeds.conf.default
    # sed -i '2i src-git passwall_luci https://github.com/Openwrt-Passwall/openwrt-passwall.git;main' feeds.conf.default
    sed -i '1i src-git luci https://github.com/coolsnowwolf/luci.git;openwrt-23.05' feeds.conf.default

    # =====================================================

    
    # ==========================================
    # 2> 安装 feeds
    # ==========================================

    log "安装 feeds..."
    ./scripts/feeds update -a
    ./scripts/feeds install -a

    # ==========================================
    # 3> 删除冲突包
    # ==========================================

    log "删除冲突包..."

    rm -rf feeds/packages/net/mosdns
    rm -rf feeds/luci/applications/luci-app-mosdns
    rm -rf feeds/packages/net/open-app-filter
    rm -rf feeds/luci/applications/luci-app-v2raya

    # ==========================================
    # 4> 更新golang
    # ==========================================

    log "更新 golang..."

    rm -rf feeds/packages/lang/golang
    retry git clone \
        --depth=1 \
        -b 26.x \
        https://github.com/sbwml/packages_lang_golang \
        feeds/packages/lang/golang

    # ==========================================
    # 5> 更新 OpenAppFilter
    # ==========================================

    log "更新 OpenAppFilter..."

    rm -rf package/OpenAppFilter
    retry git clone \
        --depth=1 \
        https://github.com/destan19/OpenAppFilter.git \
        package/OpenAppFilter

    # ==========================================
    # 6> 更新mosdns
    # ==========================================

    log "更新 mosdns..."

    rm -rf package/mosdns
    rm -rf feeds/packages/net/v2ray-geodata
    rm -rf package/v2ray-geodata

    retry git clone \
        --depth=1 \
        -b v5 \
        https://github.com/sbwml/luci-app-mosdns \
        package/mosdns

    retry git clone \
        --depth=1 \
        https://github.com/sbwml/v2ray-geodata \
        package/v2ray-geodata

    # ==========================================
    # 7> 更新theme
    # ==========================================
    # log "更新glass-theme"
    # rm -rf package/luci-theme-glass
    # retry git clone \
    #	--depth=1 \
    #	https://github.com/rchen14b/luci-theme-glass.git \
    # 	package/luci-theme-glass
    
    # ==========================================
    # 8> 更新passwall
    # ==========================================

    # 移除 openwrt feeds 自带的核心库
    log "更新passwall核心库"
    rm -rf feeds/packages/net/{xray-core,v2ray-geodata,sing-box,chinadns-ng,dns2socks,hysteria,ipt2socks,microsocks,naiveproxy,shadowsocks-libev,shadowsocks-rust,shadowsocksr-libev,simple-obfs,tcping,v2ray-plugin,xray-plugin,geoview,shadow-tls}
    rm -rf package/passwall-packages
    git clone https://github.com/Openwrt-Passwall/openwrt-passwall-packages package/passwall-packages

    # 移除 openwrt feeds 过时的luci版本
    log "更新passwall-luci"
    rm -rf feeds/luci/applications/luci-app-passwall
    rm -rf package/passwall-luci
    git clone https://github.com/Openwrt-Passwall/openwrt-passwall package/passwall-luci

    # ==========================================
    # 9> 清理缓存
    # ==========================================

    log "清理缓存..."

    rm -rf tmp

    log "feeds 更新完成"
}

# ================= 编译 =================

build_firmware() {

    check_env

    # 如果没有 .config
    [[ -f .config ]] || {
        log ".config 不存在"
        exit 1
    }

    log "生成 defconfig..."

    make defconfig

    # ==========================================
    # 下载依赖
    # ==========================================

    log "下载 dl 依赖..."
    make download -j"$JOBS"
    if command -v aria2c >/dev/null 2>&1; then
        retry make download -j"$JOBS" ARIA2C=aria2c V=s
    else
        echo "Song\$h27" | sudo -S apt install aria2 -y
        retry make download -j"$JOBS" ARIA2C=aria2c V=s
    fi
    retry make download -j1 V=s || true || log "单线程下载部分失败，继续编译..."

    # ==========================================
    # 编译
    # ==========================================

    log "开始编译..."

    make -j1 V=s

    log "编译完成"
}

# ================= 主流程 =================

main() {

    START_TIME=$(date +%s)

    log "========================================"
    log "LEDE 自动编译开始"
    log "========================================"

    case "${1:-}" in

        --clean)

            clean_build
            ;;

        --deepclean)

            DEEP_CLEAN=true
            clean_build
            ;;

        --update)

            update_source
            update_feeds
            ;;

        --build)

            build_firmware
            ;;

        "")

            DEEP_CLEAN=true
	    clean_build
            update_source
            update_feeds
            build_firmware
            ;;

        *)

            echo "用法:"
            echo "$0 [--clean|--deepclean|--update|--build]"
            exit 1
            ;;
    esac

    END_TIME=$(date +%s)
    ELAPSED=$((END_TIME - START_TIME))
    hours=$(( ELAPSED / 3600 ))
    mins=$(( ( ELAPSED % 3600 ) / 60 ))
    secs=$(( ELAPSED % 60 ))

    log "========================================"
    log "========================================"
    log "========================================"
    log "执行完成"
    log "总耗时: ${hours}小时 ${mins}分 ${secs}秒"
    log "========================================"
    log "========================================"
    log "========================================"
}

main "$@"
