#!/bin/bash
#===============================================================================
#
#          FILE: syncscript
#
#         USAGE: syncscript
#
#   DESCRIPTION: Sync all the scripts, .gamerc and .functions to all the hosts
#                優化版：每台 5 次 SSH → 2 次（scp + ssh），多台並行處理
#
#  REQUIREMENTS: A corrected /etc/hosts file
#
#         NOTES: You should make a directory www/bin/ to backup the tar balls
#
#          BUGS:  ---
#        AUTHOR: rickz (Rick Zhang), xlrickz@gmail.com
#       COMPANY: X-LEGEND Entertainment Corp.
#       CREATED: Sun Jul 17 21:53:13 EDT 2011
#      REVISION: 2.0 (optimized by parallel + reduced SSH)
#
#===============================================================================

source ~/.gamerc

egrep -q "TEST|CTRL" <<< "$HOST_NAME" \
|| exec echo "Error: You can only sync from TEST/CTRL server to other hosts."

[ -f ~/bin/crontab.default ] || crontab -l > ~/bin/crontab.default
[ -f ~/.hosts ] && cat ~/.hosts ~/bin/hosts > /etc/hosts 2> /dev/null
grep -q "CTRL" <<< "$HOST_NAME" && TEST_IP="$(grep TEST ~/bin/hosts | awk '{print $1}')"

MAX_PARALLEL=${MAX_PARALLEL:-10}
SSH_OPTS="-o StrictHostKeyChecking=no -o ConnectTimeout=10"

mkdir -p ~/www/bin
cd
if grep -q "CTRL" <<< "$HOST_NAME" ; then
    ssh TEST "tar zcf www/bin.tar.gz .gamerc bin .psqlrc .functions .bash_xl .bash_profile .bashrc"
    scp TEST:~/www/bin.tar.gz ~/www/
else
    tar zcf www/bin.tar.gz .gamerc bin .psqlrc .functions .bash_xl .bash_profile .bashrc
fi

# 同步單台機器（scp 1 次 + ssh 1 次 + gamerc update 1 次 = 3 次，原本 5 次）
sync_host() {
    local IP="$1"
    local HOSTNAME="$2"
    local LOG="/tmp/.syncscript_${IP}.log"

    {
        echo -n "Syncing scripts to ${HOSTNAME}(${IP}) ... "

        # 1. scp tar.gz
        if ! scp -q ${SSH_OPTS} www/bin.tar.gz ${IP}:~/ 2>&1; then
            echo "FAILED (scp)"
            return 1
        fi

        # 2. 一次 SSH：解壓 + 清理 + 更新 /etc/hosts
        if ! ssh ${SSH_OPTS} ${IP} "tar zxf bin.tar.gz && rm -f bin/.*.sw* bin.tar.gz && [ -f ~/.hosts ] && cat ~/.hosts ~/bin/hosts > /etc/hosts 2>/dev/null; true" 2>&1; then
            echo "FAILED (ssh)"
            return 1
        fi

        # 3. 更新 .gamerc 的 HOST_NAME
        if ! sed "s/\(HOST_NAME=\"\).*/\1${HOSTNAME}\"/" .gamerc | ssh ${SSH_OPTS} ${IP} "cat > .gamerc" 2>&1; then
            echo "FAILED (gamerc)"
            return 1
        fi

        echo "done"
    } > "$LOG" 2>&1

    return 0
}

# 收集所有要同步的 IP + hostname
declare -a SYNC_IPS=()
declare -a SYNC_NAMES=()

for IP in $(sed -n '/BELOW/,/ABOVE/p' /etc/hosts | grep "^[0-9]" | awk '{print $1}'); do
    SYNC_IPS+=("$IP")
    SYNC_NAMES+=("$(print_servername $IP)")
done

for IP in $TEST_IP; do
    SYNC_IPS+=("$IP")
    SYNC_NAMES+=("TEST")
done

TOTAL=${#SYNC_IPS[@]}
echo "Total hosts to sync: ${TOTAL} (parallel: ${MAX_PARALLEL})" | colorize yellow

# 並行同步，控制最大並行數
RUNNING=0
FAIL_COUNT=0
START_TS=$(date +%s)

for i in "${!SYNC_IPS[@]}"; do
    IP="${SYNC_IPS[$i]}"
    HOSTNAME="${SYNC_NAMES[$i]}"

    sync_host "$IP" "$HOSTNAME" &

    RUNNING=$((RUNNING + 1))

    # 達到最大並行數就等一批
    if [ "$RUNNING" -ge "$MAX_PARALLEL" ]; then
        wait
        RUNNING=0
    fi
done

# 等待剩餘的
wait

# 輸出所有結果
echo "" | colorize yellow
echo "=== Sync Results ===" | colorize yellow
for i in "${!SYNC_IPS[@]}"; do
    IP="${SYNC_IPS[$i]}"
    LOG="/tmp/.syncscript_${IP}.log"
    if [ -f "$LOG" ]; then
        cat "$LOG" | colorize green
        rm -f "$LOG"
    fi
done

END_TS=$(date +%s)
ELAPSED=$((END_TS - START_TS))
ELAPSED_MIN=$((ELAPSED / 60))
ELAPSED_SEC=$((ELAPSED % 60))

echo -n "Final check ... " | colorize yellow
mv www/bin.tar.gz www/bin/Ctrl-$(date +%Y%m%dT%H%M).tar.gz
cp -f ~/bin/updatectrl ~/www/bin/

echo "OK (${TOTAL} hosts, ${ELAPSED_MIN}m${ELAPSED_SEC}s)" | colorize green
