#!/bin/bash
set -e
_ask() {
	local _redo=0

	read resp
	case "$resp" in
	!)	echo "Type 'exit' to return to setup."
		sh
		_redo=1
		;;
	!*)	eval "${resp#?}"
		_redo=1
		;;
	esac
	return $_redo
}
ask() {
	local _question="$1" _default="$2"
	while :; do
		printf %s "$_question "
		[ -z "$_default" ] || printf "[%s] " "$_default"
		_ask && : ${resp:=$_default} && break
	done
}
ask_until() {
	resp=
	while [ -z "$resp" ] ; do
		ask "$1" "$2"
	done
}
yesno() {
	case $1 in
	[Yy]) return 0;;
	esac
	return 1
}
ask_yesno() {
	while true; do
		ask "$1" "$2"
		case "$resp" in
			Y|y|N|n) break;;
		esac
	done
	yesno "$resp"
}


select_language() {
    while true; do
        echo "Select your language:"
        echo "1. English"
        echo "2. 简体中文"
        ask_until "Please choose an option" "1"
        case $resp in
            1) 
                MSG_ARCH="Arch:"
                MSG_BOOTMODE="BootMode:"
                MSG_STORAGE_DEVICE="Storage Device:"
                MSG_ADDRESS="IP Address:"
                MSG_GATEWAY="Gateway:"
                MSG_DNS="Domain Name Server:"
                MSG_SELECT_VERSION="Select the version you want to install:"
                MSG_LTS="long-term (v7)"
                MSG_STABLE="stable (v7)"
                MSG_LTS6="long-term (v6)"
                MSG_STABLE6="stable (v6)"
                MSG_PLEASE_CHOOSE="Please choose an option:"
                MSG_UNSUPPORTED_ARCH="Error: Unsupported architecture: "
                MSG_INVALID_OPTION="Error: Invalid option!"
                MSG_ARM64_NOT_SUPPORT_V6="arm64 does not support v6 version for now."
                MSG_SELECTED_VERSION="Selected version:"
                MSG_FILE_DOWNLOAD="Download file: "
                MSG_DOWNLOAD_ERROR="Error: No wget nor curl is installed. Cannot download."
                MSG_EXTRACT_ERROR="Error: No unzip nor gunzip is installed. Cannot uncompress."
                MSG_DOWNLOAD_FAILED="Error: Download failed!"
                MSG_OPERATION_ABORTED="Error: Operation aborted."
                MSG_WARNING="Warn: All data on /dev/%s will be lost!"
                MSG_REBOOTING="Ok, rebooting..."
                MSG_ADMIN_PASSWORD="Admin Password:"
                MSG_ERROR_MOUNT="Error: Failed to mount partition"
                MSG_ERROR_LOOP="Error: Failed to setup loop device"
                MSG_AUTO_RUN_FILE_CREATED="autorun.scr file created."
                MSG_AUTO_RUN_FILE_NOT_CREATED="Warn: autorun.scr file create failed"
                MSG_CONFIRM_CONTINUE="Do you want to continue? [y/n]"
                ;;
            2) 
                MSG_ARCH="CPU架构:"
                MSG_BOOTMODE="引导模式:"
                MSG_STORAGE_DEVICE="存储设备名称:"
                MSG_ADDRESS="IP地址:"
                MSG_GATEWAY="网关地址:"
                MSG_DNS="DNS服务器:"
                MSG_SELECT_VERSION="请选择您要安装的版本:"
                MSG_LTS="长期支持版 (v7)"
                MSG_STABLE="稳定版 (v7)"
                MSG_LTS6="长期支持版 (v6)"
                MSG_STABLE6="稳定版 (v6)"
                MSG_PLEASE_CHOOSE="请选择一个选项:"
                MSG_UNSUPPORTED_ARCH="错误: 不支持的架构: "
                MSG_INVALID_OPTION="错误: 无效选项"
                MSG_ARM64_NOT_SUPPORT_V6="ARM64架构暂不支持安装v6版本"
                MSG_SELECTED_VERSION="已选择版本:"
                MSG_FILE_DOWNLOAD="下载文件: "
                MSG_DOWNLOAD_ERROR="错误: wget 或 curl 都未安装，无法下载文件。"
                MSG_EXTRACT_ERROR="错误: unzip 或 gunzip 都未安装，无法解压文件。"
                MSG_DOWNLOAD_FAILED="错误: 下载失败！"
                MSG_OPERATION_ABORTED="错误: 操作已中止。"
                MSG_WARNING="警告：/dev/%s 上的数据将会丢失！"
                MSG_REBOOTING="正在重启..."
                MSG_ADMIN_PASSWORD="管理员密码:"
                MSG_ERROR_MOUNT="错误: 挂载分区失败"
                MSG_ERROR_LOOP="错误: 设置 loop 设备失败"
                MSG_AUTO_RUN_FILE_CREATED="autorun.scr 文件已创建。"
                MSG_AUTO_RUN_FILE_NOT_CREATED="警告：autorun.scr 文件创建失败!"
                MSG_CONFIRM_CONTINUE="您是否确定继续? [y/n]"
                ;;
            *)
                echo "Error: Invalid option!"
                continue
                ;;
        esac
        break
    done
}


show_system_info() {
    ARCH=$(uname -m)
    BOOT_MODE=$( [ -d "/sys/firmware/efi" ] && echo "UEFI" || echo "BIOS" )
    echo "$MSG_ARCH $ARCH"
    echo "$MSG_BOOTMODE $BOOT_MODE"
}

confirm_storage() {
    STORAGE=$(lsblk | grep disk | head -1 | awk '{print $1}')
    ask_until "$MSG_STORAGE_DEVICE" "$STORAGE"
    STORAGE=$resp
}
confirm_address() {
    ETH=$(ip route show default | grep '^default' | sed -n 's/.* dev \([^\ ]*\) .*/\1/p')
    MAC=$(cat /sys/class/net/$ETH/address  | tr 'a-z' 'A-Z')
    ADDRESS=$(ip addr show $ETH | grep global | cut -d' ' -f 6 | head -n 1)
    GATEWAY=$(ip route list | grep default | cut -d' ' -f 3)
    if [ -f "/etc/resolv.conf" ]; then
        DNS=$(grep '^nameserver' /etc/resolv.conf | awk '{print $2}' | head -n 1)
    fi
    [ -z "$DNS" ] && DNS="8.8.8.8"
    ask_until "$MSG_ADDRESS" "$ADDRESS"
    ADDRESS=$resp
    ask_until "$MSG_GATEWAY" "$GATEWAY"
    GATEWAY=$resp
    ask_until "$MSG_DNS" "$DNS"
    DNS=$resp
}

http_get() {
    local url=$1
    local dest_file=$2
    if command -v curl >/dev/null 2>&1; then
        if [ -z "$dest_file" ]; then
            curl -Ls "$url"
        else
            curl -L -# -o "$dest_file" "$url" || { echo "$MSG_DOWNLOAD_FAILED"; exit 1; }
        fi
    elif command -v wget >/dev/null 2>&1; then
        if [ -z "$dest_file" ]; then
            wget --no-check-certificate -qO- "$url"
        else
            wget --no-check-certificate -O "$dest_file" "$url" || { echo "$MSG_DOWNLOAD_FAILED"; exit 1; }
        fi
    else
        echo "$MSG_DOWNLOAD_ERROR"
        exit 1
    fi
}

extract_zip() {
    local zip_file=$1
    local dest_file=$2
    if command -v unzip >/dev/null 2>&1; then
        unzip -p "$zip_file" > "$dest_file" || { echo "$MSG_EXTRACT_ERROR"; exit 1; }
    elif command -v gunzip >/dev/null 2>&1; then
        gunzip -c "$zip_file" > "$dest_file" || { echo "$MSG_EXTRACT_ERROR"; exit 1; }
    else
        echo "$MSG_EXTRACT_ERROR"
        exit 1
    fi
}


select_version() {
    if [[ -n "$VERSION" ]]; then
        if [[ "$VERSION" == 7.* ]]; then
            V7=1
        elif [[ "$VERSION" == 6.* ]]; then
            V7=0
        else
            echo "Error: Unsupported version $VERSION"
            exit 1
        fi
        echo "$MSG_SELECTED_VERSION $VERSION"
        return
    fi
    while true; do
        case $ARCH in
            x86_64|i386|i486|i586|i686)
                echo "$MSG_SELECT_VERSION"
                echo "1. $MSG_STABLE"
                echo "2. $MSG_LTS"
                echo "3. $MSG_STABLE6"
                echo "4. $MSG_LTS6"
                read -p "$MSG_PLEASE_CHOOSE [1-4]" version_choice
                ;; 
            aarch64)
                echo "$MSG_SELECT_VERSION"
                echo "1. $MSG_STABLE"
                echo "2. $MSG_LTS"
                read -p "$MSG_PLEASE_CHOOSE [1-2]" version_choice
                ;; 
            *)
                echo "$MSG_UNSUPPORTED_ARCH $ARCH"
                exit 1
                ;;
        esac
        case $version_choice in
            1) 
                VERSION=$(http_get "https://upgrade.mikrotik.ltd/routeros/NEWESTa7.stable" | cut -d' ' -f1)
                V7=1
                ;;
            2) 
                VERSION=$(http_get "https://upgrade.mikrotik.ltd/routeros/NEWESTa7.long-term" | cut -d' ' -f1)
                V7=1
                ;;
            3)
                if [[ "$ARCH" == "aarch64" ]]; then
                    echo "$MSG_ARM64_NOT_SUPPORT_V6"
                    continue
                fi
                VERSION=$(http_get "https://upgrade.mikrotik.ltd/routeros/NEWEST6.stable" | cut -d' ' -f1)
                V7=0
                ;;
            4)
                if [[ "$ARCH" == "aarch64" ]]; then
                    echo "$MSG_ARM64_NOT_SUPPORT_V6"
                    continue
                fi
                VERSION=$(http_get "https://upgrade.mikrotik.ltd/routeros/NEWEST6.long-term" | cut -d' ' -f1)
                V7=0
                ;;
            *)
                echo "$MSG_INVALID_OPTION"
                continue
                ;;
        esac
        echo "$MSG_SELECTED_VERSION $VERSION"
        break
    done
}

download_image(){
    case $ARCH in
        x86_64|i386|i486|i586|i686)
            if [[ $V7 == 1 && $BOOT_MODE == "BIOS" ]]; then
                IMG_URL="https://github.com/elseif/MikroTikPatch/releases/download/$VERSION/chr-$VERSION-legacy-bios.img.zip"
            else
                IMG_URL="https://github.com/elseif/MikroTikPatch/releases/download/$VERSION/chr-$VERSION.img.zip"
            fi
            ;; 
        aarch64)
             IMG_URL="https://github.com/elseif/MikroTikPatch/releases/download/$VERSION-arm64/chr-$VERSION-arm64.img.zip"
            ;; 
        *)
            echo "$MSG_UNSUPPORTED_ARCH"
            exit 1
            ;;
    esac
    echo "$MSG_FILE_DOWNLOAD $(basename "$IMG_URL")"
    http_get "$IMG_URL" "/tmp/chr.img.zip"
    cd /tmp
    extract_zip "chr.img.zip" chr.img
}

create_autorun() {
    LOOP=$(losetup -f)
    if losetup -P "$LOOP" chr.img; then
        sleep 1
        MNT=/tmp/chr
        mkdir -p $MNT
        PARTITION=$([ "$V7" == 1 ] && echo "p2" || echo "p1")
        if mount "${LOOP}${PARTITION}" "$MNT"; then
            confirm_address
            RANDOM_ADMIN_PASS=$(head -c 512 /dev/urandom | tr -dc 'A-HJ-KMNP-Za-hj-kmnp-z2-9' | head -c 16)
            ask_until "$MSG_ADMIN_PASSWORD" "$RANDOM_ADMIN_PASS"
            RANDOM_ADMIN_PASS=$resp
            cat <<EOF > "$MNT/rw/autorun.scr"
/tool mac-server set allowed-interface-list=none 
/tool mac-server mac-winbox set allowed-interface-list=none 
/tool mac-server ping set enabled=no
/ip neighbor discovery-settings set discover-interface-list=none 
/tool bandwidth-server set enabled=no 
/ip dns set allow-remote-requests=no
/user set admin password="$RANDOM_ADMIN_PASS"
/ip dns set servers=$DNS
/ip address add address=$ADDRESS interface=[/interface ethernet get [find mac-address=$MAC] name]
/ip route add gateway=$GATEWAY
EOF
            cat "$MNT/rw/autorun.scr"
            echo "$MSG_AUTO_RUN_FILE_CREATED"
            umount $MNT
            losetup -d "$LOOP"
        else
            losetup -d "$LOOP"
            echo "$MSG_ERROR_MOUNT $PARTITION"
            echo "$MSG_AUTO_RUN_FILE_NOT_CREATED"
        fi
    else
        echo "$MSG_ERROR_LOOP"
        echo "$MSG_AUTO_RUN_FILE_NOT_CREATED"
    fi
}


write_reboot() {
	confirm_storage
    printf "$MSG_WARNING\n" "$STORAGE"
    ask_yesno "$MSG_CONFIRM_CONTINUE"
    if [ $? -ne 0 ]; then
        echo "$MSG_OPERATION_ABORTED"
        exit 1
    fi
    sync
    dd if=chr.img of=/dev/$STORAGE bs=4M conv=fsync
    echo "$MSG_REBOOTING"
    echo 1 > /proc/sys/kernel/sysrq 2>/dev/null || true
    echo b > /proc/sysrq-trigger 2>/dev/null || true
    reboot -f
}

select_language
show_system_info
select_version
download_image
create_autorun
write_reboot
exit 0
