#!/bin/bash
# shellcheck disable=SC2155
if ! type "include" > /dev/null 2>&1; then
  include() {
  . "$(cd "$(dirname "$1")" && pwd)/${2}";
  };
fi
include "${BASH_SOURCE[0]}" ../pragma_once.bash
if ! pragma_once ${BASH_SOURCE[0]}; then return 0; fi
include "${BASH_SOURCE[0]}" ./global_rely/export.bash
# shellcheck source=./global_rely/export.bash



# 这种是为了语法提示
# shellcheck source=./global_rely/log.bash
# shellcheck source=./global_rely/stack_trace.bash


check_baidu_network() {
  local baidu_domain="www.baidu.com"  # 要检测的目标域名
  echo "正在检测是否能连接到 $baidu_domain..."

  # 使用 ping 命令检测是否能连接到 baidu.com
  if ping -c 1 "$baidu_domain" > /dev/null 2>&1; then
    echo "$baidu_domain 网络连接正常。"
    return 0  # 连接正常
  else
    echo "无法连接到 $baidu_domain，网络不可达。"
    return 1  # 网络不可达
  fi
}

# 用法：
#   chromium_net_check_report                 # 检测一次并输出报告
#   chromium_net_check_report --wait          # 循环等待，直到“任一方式可用”为止，并持续输出报告
#   chromium_net_check_report --wait 300      # 最多等待 300 秒
#
# 报告包含：
#   1) DNS 解析是否成功
#   2) ping(ICMP) 是否通（注意：TUN/代理下可能一直不通）
#   3) curl HTTPS HEAD 是否通（更贴近实际拉代码/访问网页）
#
chromium_net_check_report() {
  local host="chromium.googlesource.com"
  local wait_mode=0
  local timeout=0

  if [[ "${1:-}" == "--wait" ]]; then
    wait_mode=1
    timeout="${2:-0}"   # 0 = 无限等
  fi

  # ping 参数兼容：Windows (MSYS/Git-Bash) 用 -n/-w(ms)，Linux/macOS 用 -c/-W(s)
  local ping_count_flag="-c"
  local ping_timeout_flag="-W"
  local ping_timeout_val="1"
  case "$(uname -s 2>/dev/null | tr '[:upper:]' '[:lower:]')" in
  mingw*|msys*|cygwin*)
    ping_count_flag="-n"
    ping_timeout_flag="-w"
    ping_timeout_val="1000"  # ms
    ;;
  esac

  _ts() {
    date "+%Y-%m-%d %H:%M:%S" 2>/dev/null || echo ""
  }

  _dns_check() {
    # 尽量不用 nslookup 输出噪音：只判断能不能解析出 IP
    if command -v getent >/dev/null 2>&1; then
      getent hosts "$host" >/dev/null 2>&1
      return $?
    elif command -v nslookup >/dev/null 2>&1; then
      nslookup "$host" >/dev/null 2>&1
      return $?
    else
      return 127
    fi
  }

  _ping_check() {
    ping "${ping_count_flag}" 1 "${ping_timeout_flag}" "${ping_timeout_val}" "$host" >/dev/null 2>&1
    return $?
  }

  _curl_check() {
    if ! command -v curl >/dev/null 2>&1; then
      return 127
    fi
    curl -fsSI --max-time 6 "https://${host}/" >/dev/null 2>&1
    return $?
  }

  _one_report() {
    local dns_rc ping_rc curl_rc
    local dns_status ping_status curl_status
    local hint=()

    dns_rc=0; ping_rc=0; curl_rc=0

    _dns_check; dns_rc=$?
    _ping_check; ping_rc=$?
    _curl_check; curl_rc=$?

    case "$dns_rc" in
    0) dns_status="OK" ;;
    127) dns_status="N/A(no nslookup/getent)" ;;
    *) dns_status="FAIL" ;;
    esac

    case "$ping_rc" in
    0) ping_status="OK" ;;
    *) ping_status="FAIL" ;;
    esac

    case "$curl_rc" in
    0) curl_status="OK" ;;
    127) curl_status="N/A(no curl)" ;;
    *) curl_status="FAIL" ;;
    esac

    echo "==================== Chromium Network Report ===================="
    echo "Time: $(_ts)"
    echo "Host: ${host}"
    echo "------------------------------------------------------------------"
    echo "DNS  : ${dns_status}"
    echo "PING : ${ping_status}"
    echo "CURL : ${curl_status}  (HTTPS HEAD https://${host}/)"
    echo "------------------------------------------------------------------"

    # 解释/建议（按组合给）
    if [[ "$dns_rc" != 0 && "$dns_rc" != 127 ]]; then
      hint+=("DNS 解析失败：检查系统 DNS/Clash DNS 设置，或是否被劫持/污染。")
    fi

    if [[ "$curl_rc" == 0 ]]; then
      hint+=("HTTPS 可访问：用于 gclient/git 拉取通常已经足够。")
    else
      if [[ "$curl_rc" == 127 ]]; then
        hint+=("未检测到 curl：建议安装/启用 curl（Git-Bash 通常自带）。")
      else
        hint+=("HTTPS 不可访问：通常表示代理/TUN 未生效或证书/网络被拦。")
      fi
    fi

    if [[ "$ping_rc" != 0 ]]; then
      hint+=("PING 不通：在 Clash TUN/代理下可能正常（ICMP 常被丢弃）。不要只以 ping 为唯一标准。")
    fi

    if [[ "${#hint[@]}" -gt 0 ]]; then
      echo "Notes:"
      local i
      for i in "${hint[@]}"; do
        echo "  - $i"
      done
    fi

    echo "=================================================================="

    # 返回码策略：
    # 0 = curl OK（认为网络可用）
    # 1 = curl FAIL（不可用）
    if [[ "$curl_rc" == 0 ]]; then
      return 0
    fi
    return 1
  }

  if [[ "$wait_mode" -eq 0 ]]; then
    _one_report
    return $?
  fi

  local start_ts now_ts elapsed
  start_ts=$(date +%s 2>/dev/null || echo 0)

  echo "[WAIT] 循环检测中：直到 CURL 可访问为止（timeout=${timeout}s，0=无限）"
  while true; do
    if _one_report; then
      echo "[DONE] CURL 已可访问：网络就绪"
      return 0
    fi

    if [[ "$timeout" -gt 0 && "$start_ts" -ne 0 ]]; then
      now_ts=$(date +%s 2>/dev/null || echo 0)
      elapsed=$((now_ts - start_ts))
      if [[ "$elapsed" -ge "$timeout" ]]; then
        echo "[TIMEOUT] 等待超过 ${timeout}s，仍不可访问 https://${host}/"
        return 2
      fi
    fi

    sleep 3
  done
}




print_important_var() {
  local var=$1           # 传入的变量名
  local val=${!var} # 使用 eval 来获取变量的值
  echo "【${var}】=== 【${val}】"
}







load_PATH(){
  local tmp
  merge_args tmp ":" "$@"
  export PATH="${tmp}${PATH:+:$PATH}"
}

load_LIBRARY_PATH(){
  local tmp
  merge_args tmp ":" "$@"
  export LIBRARY_PATH="${tmp}${LIBRARY_PATH:+:$LIBRARY_PATH}"
}

load_LD_LIBRARY_PATH(){
  local tmp
  merge_args tmp ":" "$@"
  export LD_LIBRARY_PATH="${tmp}${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH}"
}

load_ALL(){
  load_PATH "$@"
  load_LIBRARY_PATH "$@"
  load_LD_LIBRARY_PATH "$@"
}
save_env() {
  export saved_PATH="$PATH"
  export saved_LIBRARY_PATH="$LIBRARY_PATH"
  export saved_LD_LIBRARY_PATH="$LD_LIBRARY_PATH"
}

restore_env() {
  export PATH="$saved_PATH"
  export LIBRARY_PATH="$saved_LIBRARY_PATH"
  export LD_LIBRARY_PATH="$saved_LD_LIBRARY_PATH"
}

# 公用函数：打印指定环境变量的路径
print_env_path() {
  local env_var="$1"  # 环境变量名
  local env_value="${!env_var}"  # 获取环境变量的值
    # 输出环境变量的路径
  log_info "[ $env_var ]："
  IFS=":" read -r -a paths <<< "$env_value"
  i=0
  for path in "${paths[@]}"; do
    # 使用 printf 格式化 $i，确保它是 3 位，右对齐
    formatted_i=$(printf "%2d" "$i")
    log_info "$formatted_i: $path"
    ((i++)) || true
  done
}


print_env() {
  log_trace "========================== 【 打印环境变量 】 =========================="
  print_env_path "PATH"
  print_env_path "LD_LIBRARY_PATH"
  print_env_path "LD_RUN_PATH"
  print_env_path "LIBRARY_PATH"
  log_trace "========================== 【 打印环境变量 】 =========================="
}


print_remain_args(){
  local err=$1
  shift 1
  local i=0
  log_error "msg:${err}"
  for param in "$@"; do
    log_error "[%2d] $param" $i
    ((i++))
  done
}





pragma_once() {
  # 1. 转换为绝对路径以确保唯一性
  local abs_path
  abs_path=$(realpath "$1" 2>/dev/null || echo "$1")
  if [ ! -e "$abs_path" ]; then
    log_info "错误: 文件 '$1' 不存在。"
    exit 1
  fi

  # 2. 生成 Key（只保留字母数字，其他转下划线）
  local key="key_$(echo "$abs_path" | sed 's/[^a-zA-Z0-9]/_/g')"

  # 3. 精确匹配检查
  # 我们在 map 的两端和 key 的两端都加上分隔符 |
  if [[ "$loaded_scripts_map" == *"|$key|"* ]]; then
    return 1  # 已经加载过了
  else
    # 第一次加载，存入时带上分隔符
    # 如果 map 为空，初始化为 |key|；如果不为空，追加 key|
    if [[ -z "$loaded_scripts_map" ]]; then
      loaded_scripts_map="|$key|"
    else
      loaded_scripts_map="${loaded_scripts_map}${key}|"
    fi
    return 0  # 允许加载
  fi
}
# 使用方式
# if pragma_once "${BASH_SOURCE[0]}"; then
# fi





centos7_6_init_iso_root() {
  sudo yum --disablerepo=* --enablerepo=wyc groupinstall "Development Tools" -y
  sudo yum --disablerepo=* --enablerepo=wyc install gmp-devel mpfr-devel libmpc-devel openssl mesa-libGL-devel -y
}


check_directory() {
  local dir="$1"
  if [ ! -d "$dir" ]; then
    echo "错误: 目录不存在: $dir"
    return 1
  fi
  return 0
}

check_directory_var() {
  local var_name="$1"
  local dir="${!var_name}"

  if [ -z "$var_name" ]; then
    echo "错误: 未传入变量名"
    return 1
  fi

  if [ -z "$dir" ]; then
    echo "错误: 变量未定义或为空: $var_name"
    return 1
  fi

  if [ ! -d "$dir" ]; then
    echo "错误: 目录不存在: $var_name=$dir"
    return 1
  fi

  return 0
}



check_file() {
  local file="$1"
  if [ ! -f "$file" ]; then
    echo "错误: 文件不存在: $file"
    return 1
  fi
  return 0
}

check_file_ex() {
  local prefix="$1"
  local file="$2"
  if [ ! -f "$file" ]; then
    echo "【${prefix}】 错误: 文件不存在: $file"
    return 1
  fi
  return 0
}

check_file_var() {
  local var_name="$1"
  local file="${!var_name}"

  if [ -z "$var_name" ]; then
    echo "错误: 未传入变量名"
    return 1
  fi

  if [ -z "$file" ]; then
    echo "错误: 变量未定义或为空: $var_name"
    return 1
  fi

  if [ ! -f "$file" ]; then
    echo "错误: 文件不存在: $var_name=$file"
    return 1
  fi

  return 0
}

is_absolute_directory() {
  local dir_path="$1"
  if [[ "$dir_path" != /* ]] || [ ! -d "$dir_path" ]; then
    return 1
  fi
  return 0
}

is_absolute_file() {
  local file_path="$1"
  if [[ "$file_path" != /* ]] || [ ! -f "$file_path" ]; then
    return 1
  fi
  return 0
}

is_absolute_elf() {
  local path="$1"
  if [[ "$path" != /* ]]; then
    echo "Not an absolute path: $path"
    return 1
  fi
  if [[ ! -f "$path" ]]; then
    echo "File not found: $path"
    return 1
  fi
  if ! file "$path" | grep -q 'ELF'; then
    echo "Not an ELF file: $path"
    return 1
  fi
  return 0
}

is_valid_absolute_path_format() {
  local input="$1"
  if [[ "$input" =~ ^(/[^:/]+)+(:/[^:/]+)+$ ]]; then
    return 1
  fi
  echo "Invalid format: $input"
  return 0
}

#!/bin/bash

# 压缩函数：将目录压缩为 .tar.gz 格式
compress_directory_tar_gz() {
  local source_dir="$1"   # 源目录
  local install_root="$2" # 目标目录
  local archive_name="$3" # 压缩包名称
  if [ ! -d "$source_dir" ]; then
    echo "compress_directory Error: Source directory '$source_dir' does not exist!"
    return 1
  fi
  echo "Compressing '$source_dir' to '$install_root/$archive_name'..."
  # 去除硬链接
#  local workdir="$(dirname "$source_dir")"
#  local a2="$(basename "$source_dir")"
  tar --hard-dereference -czvf "$install_root/$archive_name" -C "${source_dir}" .

  if [ $? -eq 0 ]; then
    echo "Compression successful! $install_root/$archive_name"
  else
    echo "Compression failed!  $install_root/$archive_name"
    return 1
  fi
}


compress_directory_tar_gz() {
  local source_dir="$1"   # 源目录
  local install_root="$2" # 目标目录
  local archive_name="$3" # 压缩包名称
  if [ ! -d "$source_dir" ]; then
    echo "compress_directory Error: Source directory '$source_dir' does not exist!"
    return 1
  fi
  echo "Compressing '$source_dir' to '$install_root/$archive_name'..."
  # 去除硬链接
#  local workdir="$(dirname "$source_dir")"
#  local a2="$(basename "$source_dir")"
  tar --hard-dereference -czvf "$install_root/$archive_name" -C "${source_dir}" .

  if [ $? -eq 0 ]; then
    echo "Compression successful! $install_root/$archive_name"
  else
    echo "Compression failed!  $install_root/$archive_name"
    return 1
  fi
}

# 解压函数：将 .tar.gz 文件解压到目标目录
compress_directory_tar_gz_copy() {
  local source_dir="$1"
  local install_root="$2"
  local archive_name="$3"

  if [ ! -d "$source_dir" ]; then
    echo "compress_directory Error: Source directory '$source_dir' does not exist!"
    return 1
  fi

  echo "Compressing '$source_dir' to '$install_root/$archive_name'..."

  tar --dereference --hard-dereference -czvf "$install_root/$archive_name" -C "${source_dir}" .

  if [ $? -eq 0 ]; then
    echo "Compression successful! $install_root/$archive_name"
  else
    echo "Compression failed! $install_root/$archive_name"
    return 1
  fi
}

# 示例用法
# compress_directory "/path/to/source_directory" "/path/to/your/install_root" "your_archive_name.tar.gz"
# decompress_archive "/path/to/your/install_root/your_archive_name.tar.gz" "/path/to/target_directory"


# 通用检查函数：检查值是否在给定范围内
check_value_in_range() {
  local param_name="$1"  # 参数名称
  shift  # 移除参数名称，剩下的是有效范围

  # 获取参数的当前值
  local value="${!param_name}"

  # 遍历所有范围值
  for range_value in "$@"; do
    if [[ "$value" == "$range_value" ]]; then
      return 0  # 找到匹配的值，返回成功
    fi
  done

  # 如果没有找到匹配值，打印错误并退出
  log_error "ERROR: '$param_name' has invalid value '$value'. Valid values are: $*"
  exit 77
}

check_ret_exit() {
  local ret=$?
  local msg="$1"

  if (( ret != 0 )); then
    if [[ -z "${msg//[[:space:]]/}" ]]; then
      msg="命令执行失败"
    fi
    log_error "${msg} ret=${ret}"
    exit "$ret"
  fi
}


clear_dir_contents() {
  local dir="$1"

  # 参数为空时直接报错返回
  if [[ -z "$dir" ]]; then
    echo "[ERROR] clear_dir_contents: 目录参数不能为空" >&2
    return 1
  fi

  # 目录不存在时跳过，不报错
  if [[ ! -d "$dir" ]]; then
    echo "[INFO] 目录不存在，跳过清空: $dir"
    return 0
  fi

  # 删除普通文件和普通目录
  rm -rf "${dir:?}/"*

  # 删除隐藏文件/目录（例如 .git、.cache），但不匹配 . 和 ..
  rm -rf "${dir:?}/".[!.]*

  # 删除以两个点开头的隐藏文件/目录，但仍然不会匹配 .. 本身
  rm -rf "${dir:?}/"..?*

  echo "[OK] 已清空目录内容: $dir"
}

check_and_create_dir_var() {
  local dir_var=$1  # 传入的变量名
  local dir_path=${!dir_var}  # 使用 eval 来获取变量的值

  # 检查目录是否存在
  if [ -d "$dir_path" ]; then
    echo "【${dir_var}】: 【$dir_path】"
    :
  else
    # 如果目录不存在，则尝试创建目录
    echo "【${dir_var}】目录不存在，正在创建: $dir_path"
    mkdir -p "$dir_path"  # 创建目录，-p 确保父目录也被创建
    if [ $? -ne 0 ]; then
      echo "【${dir_var}】错误: 创建目录失败 $dir_path"
      exit 1  # 返回失败代码
    else
      echo "【${dir_var}】目录创建成功: $dir_path"
    fi
  fi
}

check_and_create_dir() {
  local dir="$1"
  # 非空判断：空字符串或全空白都算空
  if [[ -z "${dir//[[:space:]]/}" ]]; then
    log_error "ERROR: dir is empty"
    exit 4
  fi

  if [[ ! -d "$dir" ]]; then
    log_info "Attempting to create the directory... 【${dir}】"
    mkdir -p "$dir"
    if [[ $? -ne 0 ]]; then
      log_error "ERROR: Failed to create directory 【${dir}】"
      exit 5
    fi
    chmod 777 "$dir"
    if [[ $? -ne 0 ]]; then
      log_error "ERROR: Failed to chmod 777 【${dir}】"
      exit 6
    fi
  fi
}



#  使用示例
#  declare -a files
#  regex_glob_files files "/ae/bash/0_git_cache_dir/binutils-gdb" "/ae/bash/0_git_cache_dir/binutils-gdb/build" '.*\.(c|h)$'
#  echo "count: ${#files[@]}"
#  printf '%s\n' "${files[@]}"
#  i=0
#  for f in "${files[@]}"; do
#    printf '%d: %s\n' "$i" "$f"
#    ((i++))
#  done

regex_glob_files() {
  if [ $# -lt 4 ]; then
    return 1
  fi

  local ret_name="$1"
  local include_path="$2"
  local exclude_path="$3"
  local regex_expr="$4"

  if [ -z "$ret_name" ]; then
    return 1
  fi

  local -n ret="$ret_name"
  ret=()

  if [ -z "$include_path" ] || [ ! -e "$include_path" ]; then
    return 0
  fi

  local include_abs=""
  local exclude_abs=""
  local item=""
  local base_name=""

  include_abs=$(realpath "$include_path")

  if [ -n "$exclude_path" ] && [ -e "$exclude_path" ]; then
    exclude_abs=$(realpath "$exclude_path")
  fi

  if [ -f "$include_abs" ]; then
    if [ -n "$exclude_abs" ] && [ "$include_abs" = "$exclude_abs" ]; then
      return 0
    fi

    if [ -n "$regex_expr" ]; then
      base_name="${include_abs##*/}"
      if [[ "$base_name" =~ $regex_expr ]]; then
        ret+=("$include_abs")
      fi
    else
      ret+=("$include_abs")
    fi

    return 0
  fi

  if [ -d "$include_abs" ]; then
    while IFS= read -r item; do
      if [ -n "$regex_expr" ]; then
        base_name="${item##*/}"
        if [[ "$base_name" =~ $regex_expr ]]; then
          ret+=("$item")
        fi
      else
        ret+=("$item")
      fi
    done < <(
      if [ -n "$exclude_abs" ]; then
        find "$include_abs" \
          \( -path "$exclude_abs" -o -path "$exclude_abs/*" \) -prune -o \
          -type f -print
      else
        find "$include_abs" -type f -print
      fi
    )

    return 0
  fi

  return 0
}


#     *	任意长度任意字符（可为0）	*.c	a.c, test.c	a.cpp
#     ?	任意1个字符	a?.txt	ab.txt	a.txt, abc.txt
#     [abc]	匹配集合中一个字符	file[12].txt	file1.txt	file3.txt
#     [a-z]	匹配范围内一个字符	file[a-z].txt	filea.txt	fileA.txt
#     [!abc]	不在集合中的一个字符	file[!0-9].txt	filea.txt	file1.txt
glob_files_by_name() {
  if [ $# -lt 4 ]; then
    return 1
  fi

  local ret_name="$1"
  local include_path="$2"
  local exclude_path="$3"
  local name_pattern="$4"

  local -n ret="$ret_name"
  ret=()

  [ -z "$include_path" ] && return 0
  [ ! -e "$include_path" ] && return 0

  local include_abs
  local exclude_abs=""

  include_abs=$(realpath "$include_path")

  if [ -n "$exclude_path" ] && [ -e "$exclude_path" ]; then
    exclude_abs=$(realpath "$exclude_path")
  fi

  if [ -f "$include_abs" ]; then
    local base_name="${include_abs##*/}"
    if [[ "$base_name" == $name_pattern ]]; then
      ret+=("$include_abs")
    fi
    return 0
  fi

  while IFS= read -r item; do
    ret+=("$item")
  done < <(
    if [ -n "$exclude_abs" ]; then
      find "$include_abs" \
        \( -path "$exclude_abs" -o -path "$exclude_abs/*" \) -prune -o \
        -type f -name "$name_pattern" -print
    else
      find "$include_abs" -type f -name "$name_pattern" -print
    fi
  )
}

# 生成命令行脚本 给某些makefile使用

_generate_case_dispatch_script_begin() {
  if [ $# -ne 1 ]; then
    return 1
  fi

  local ret_name="$1"
  local -n ret="$ret_name"

  ret=""
  ret+=$'#!/usr/bin/env bash\n'
  ret+=$'set -euo pipefail\n'
  ret+=$'\n'
  ret+=$'case "${2:-${1:-}}" in\n'
}

_generate_case_dispatch_script_append_case() {
  if [ $# -ne 3 ]; then
    return 1
  fi

  local ret_name="$1"
  local case_label="$2"
  local case_value="$3"

  if [ -z "$case_label" ] || [ -z "$case_value" ]; then
    return 1
  fi

  local -n ret="$ret_name"

  ret+="${case_label})"$'\n'
  printf -v ret '%s  printf '\''%%s'\\\\n\'' "%s"\n' "$ret" "$case_value"
  ret+=$'  ;;\n'
}

_generate_case_dispatch_script_end() {
  if [ $# -ne 1 ]; then
    return 1
  fi

  local ret_name="$1"
  local -n ret="$ret_name"

  ret+=$'*)\n'
  ret+=$'  echo "unsupported args: $*" >&2\n'
  ret+=$'  exit 1\n'
  ret+=$'  ;;\n'
  ret+=$'esac\n'
  ret+=$'exit 0\n'
}

generate_case_dispatch_script_string() {
  if [ $# -lt 3 ]; then
    return 1
  fi

  local ret_name="$1"
  shift

  if [ -z "$ret_name" ]; then
    return 1
  fi

  if [ $(( $# % 2 )) -ne 0 ]; then
    return 1
  fi

  _generate_case_dispatch_script_begin "$ret_name" || return 1

  local case_label=""
  local case_value=""

  while [ $# -gt 0 ]; do
    case_label="$1"
    case_value="$2"
    shift 2
    _generate_case_dispatch_script_append_case "$ret_name" "$case_label" "$case_value" || return 1
  done

  _generate_case_dispatch_script_end "$ret_name" || return 1
  return 0
}



return 0