#!/bin/bash
# EG Linux 构建脚本 - 使用 Nuitka 编译 + AppImage 打包（保守白名单版）
# 用法: ./build_linux.sh [版本号] [--clean] [--skip-compile] [--deb]

set -e

# 配置
VERSION=${1:-"1.0.0"}
CLEAN=false
SKIP_COMPILE=false
BUILD_DEB=false

# 解析参数
for arg in "$@"; do
    case $arg in
        --clean)
            CLEAN=true
            shift
            ;;
        --skip-compile)
            SKIP_COMPILE=true
            shift
            ;;
        --deb)
            BUILD_DEB=true
            shift
            ;;
    esac
done

# 路径配置
PROJECT_ROOT="$(cd "$(dirname "$0")/.." && pwd)"
DIST_DIR="$PROJECT_ROOT/dist"
BUILD_DIR="$PROJECT_ROOT/build"
NUITKA_DIR="$BUILD_DIR/nuitka"
APPDIR="$BUILD_DIR/EG_$VERSION.AppDir"
OUTPUT_NAME="EG_$VERSION"

# 应用信息
APP_NAME="EG"
COMPANY_NAME="EG Team"
APP_DESCRIPTION="EG 3D Editor and Game Engine"

# 需要包含的数据目录
DATA_DIRS=(
    # 配置和资源
    "config"
    "icons"
    "Resources"
    "tex"
    "templates"
    
    # 核心模块
    "core"
    "gui"
    "project"           # 项目管理模块
    "scene"
    "scripts"
    "ssbo_component"
    "tools"
    "TransformGizmo"
    "ui"
    
    # 引擎和扩展
    "RenderPipelineFile"
    "vr_actions"
    
    # 项目模板
    "new"                # 默认空项目模板
    "demo"
)

# 需要包含的单个文件
DATA_FILES=(
    "imgui.ini"
)

REQUIRED_PACKAGES=(
    "panda3d"
    "direct"
    "imgui_bundle"
    "p3dimgui"
    "openvr"
    "RenderPipelineFile"
    "rpcore"
    "rplibs"
    "rpplugins"
    "core"
    "scene"
    "project"
    "ui"
    "gui"
    "scripts"
    "ssbo_component"
    "tools"
    "TransformGizmo"
    "vr_actions"
)

OPTIONAL_PACKAGES=(
    "plugins"
    "gltf"
    "playwright"
    "PyQt5"
)

OPTIONAL_MODULES=(
    "playwright.async_api"
    "win32gui"
    "win32con"
    "PyQt5.QtCore"
    "PyQt5.QtGui"
    "PyQt5.QtWidgets"
)

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m' # No Color

# 辅助函数
log_info() {
    echo -e "${BLUE}[INFO]${NC} $1"
}

log_success() {
    echo -e "${GREEN}[OK]${NC} $1"
}

log_warning() {
    echo -e "${YELLOW}[WARN]${NC} $1"
}

log_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

log_step() {
    local step=$1
    local total=$2
    local msg=$3
    echo ""
    echo -e "${YELLOW}[$step/$total]${NC} $msg"
}

python_importable() {
    local module_name="$1"
    python3 -c "import importlib.util, sys; sys.exit(0 if importlib.util.find_spec('$module_name') else 1)" >/dev/null 2>&1
}

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

echo "========================================"
echo "  EG Linux Builder v$VERSION"
echo "========================================"
echo "项目路径: $PROJECT_ROOT"

# 步骤 1: 清理
log_step 1 6 "清理旧构建..."

if [ "$CLEAN" = true ]; then
    rm -rf "$BUILD_DIR"
    rm -rf "$DIST_DIR"
    log_success "已清理所有构建文件"
fi

mkdir -p "$BUILD_DIR"
mkdir -p "$DIST_DIR"

# 步骤 2: 环境检查
log_step 2 6 "检查构建环境..."

# 检查必要的命令
for cmd in python3 pip3 gcc g++; do
    if ! command -v $cmd &> /dev/null; then
        log_error "$cmd 未安装"
        exit 1
    fi
done

PYTHON_VERSION=$(python3 --version 2>&1)
log_success "Python: $PYTHON_VERSION"

# 检查并安装构建依赖
log_info "检查构建依赖..."
pip3 install -q nuitka pyinstaller 2>/dev/null || true
log_success "构建依赖已就绪"

# 安装项目依赖
log_info "检查项目依赖..."
pip3 install -q -r "$PROJECT_ROOT/requirements/requirements-minimal.txt" 2>/dev/null || log_warning "部分依赖可能安装失败"
log_success "项目依赖已就绪"

# 步骤 3: Nuitka 编译
if [ "$SKIP_COMPILE" = false ]; then
    log_step 3 6 "使用 Nuitka 编译主程序..."
    
    cd "$PROJECT_ROOT"
    
    REQUIRED_PACKAGE_ARGS=()
    for package in "${REQUIRED_PACKAGES[@]}"; do
        REQUIRED_PACKAGE_ARGS+=("--include-package=$package")
    done

    OPTIONAL_PACKAGE_ARGS=()
    for package in "${OPTIONAL_PACKAGES[@]}"; do
        if python_importable "$package"; then
            OPTIONAL_PACKAGE_ARGS+=("--include-package=$package")
            log_info "检测到可选包并纳入打包: $package"
        fi
    done

    OPTIONAL_MODULE_ARGS=()
    for module in "${OPTIONAL_MODULES[@]}"; do
        if python_importable "$module"; then
            OPTIONAL_MODULE_ARGS+=("--include-module=$module")
            log_info "检测到可选模块并纳入打包: $module"
        fi
    done

    # 构建 Nuitka 选项
    NUITKA_OPTS=(
        "--standalone"
        "--follow-import-to=rpcore"
        "--follow-import-to=rpplugins"
        "--follow-import-to=core"
        "--follow-import-to=scene"
        "--follow-import-to=project"
        "--follow-import-to=ui"
        "--nofollow-import-to=tkinter,test,unittest,setuptools,pip"
        "--linux-onefile-icon=icons/app.png"
        "--lto=no"
        "--jobs=$(nproc)"
        "--output-dir=$NUITKA_DIR"
        "--remove-output"
    )

    NUITKA_OPTS+=("${REQUIRED_PACKAGE_ARGS[@]}")
    NUITKA_OPTS+=("${OPTIONAL_PACKAGE_ARGS[@]}")
    NUITKA_OPTS+=("${OPTIONAL_MODULE_ARGS[@]}")
    
    log_info "开始编译 (可能需要几分钟)..."
    python3 -m nuitka "${NUITKA_OPTS[@]}" Start_Run.py
    
    if [ $? -ne 0 ]; then
        log_error "Nuitka 编译失败"
        exit 1
    fi
    
    log_success "编译成功"
else
    log_step 3 6 "跳过编译 (--skip-compile)"
fi

# 步骤 4: 准备 AppDir
log_step 4 6 "准备 AppDir..."

rm -rf "$APPDIR"
mkdir -p "$APPDIR/usr/bin"
mkdir -p "$APPDIR/usr/lib/EG"
mkdir -p "$APPDIR/usr/share/applications"
mkdir -p "$APPDIR/usr/share/icons/hicolor/256x256/apps"
mkdir -p "$APPDIR/usr/share/icons/hicolor/128x128/apps"
mkdir -p "$APPDIR/usr/share/icons/hicolor/64x64/apps"
mkdir -p "$APPDIR/usr/share/metainfo"

# 复制 Nuitka standalone 目录
DIST_SOURCE="$NUITKA_DIR/Start_Run.dist"
if [ ! -d "$DIST_SOURCE" ]; then
    log_error "找不到编译后的 standalone 目录: $DIST_SOURCE"
    exit 1
fi

cp -r "$DIST_SOURCE/"* "$APPDIR/usr/lib/EG/"

if [ -f "$APPDIR/usr/lib/EG/Start_Run.bin" ]; then
    cp "$APPDIR/usr/lib/EG/Start_Run.bin" "$APPDIR/usr/bin/EG"
elif [ -f "$APPDIR/usr/lib/EG/Start_Run" ]; then
    cp "$APPDIR/usr/lib/EG/Start_Run" "$APPDIR/usr/bin/EG"
else
    EXE_SOURCE=$(find "$APPDIR/usr/lib/EG" -maxdepth 1 -type f -executable | head -1)
    if [ -z "$EXE_SOURCE" ]; then
        log_error "找不到可执行文件"
        exit 1
    fi
    cp "$EXE_SOURCE" "$APPDIR/usr/bin/EG"
fi

chmod +x "$APPDIR/usr/bin/EG"
log_success "复制可执行文件和 standalone 运行时"

# 复制数据目录
COPIED=0
for dir in "${DATA_DIRS[@]}"; do
    if [ -d "$PROJECT_ROOT/$dir" ]; then
        cp -r "$PROJECT_ROOT/$dir" "$APPDIR/usr/lib/EG/"
        # 清理 Python 缓存
        find "$APPDIR/usr/lib/EG/$dir" -type d -name "__pycache__" -exec rm -rf {} + 2>/dev/null || true
        find "$APPDIR/usr/lib/EG/$dir" -name "*.pyc" -delete 2>/dev/null || true
        log_success "复制目录: $dir"
        ((COPIED++))
    else
        log_warning "目录不存在: $dir"
    fi
done
log_success "共复制 $COPIED 个数据目录"

# 复制单个文件
for file in "${DATA_FILES[@]}"; do
    if [ -f "$PROJECT_ROOT/$file" ]; then
        cp "$PROJECT_ROOT/$file" "$APPDIR/usr/lib/EG/"
        log_success "复制文件: $file"
    fi
done

# 创建 .desktop 文件
cat > "$APPDIR/usr/share/applications/EG.desktop" << EOF
[Desktop Entry]
Name=EG
Name[zh_CN]=EG 编辑器
Comment=$APP_DESCRIPTION
Comment[zh_CN]=EG 3D 编辑器和游戏引擎
Exec=EG
Icon=EG
Type=Application
Categories=Graphics;3DGraphics;Development;Game;
MimeType=application/x-eg-project;
Terminal=false
StartupNotify=true
StartupWMClass=EG
Keywords=3D;Editor;Game;Engine;Panda3D;
EOF

# 创建 AppStream metadata (用于软件中心)
cat > "$APPDIR/usr/share/metainfo/EG.appdata.xml" << EOF
<?xml version="1.0" encoding="UTF-8"?>
<component type="desktop-application">
  <id>com.yourcompany.EG</id>
  <metadata_license>CC0-1.0</metadata_license>
  <project_license>Proprietary</project_license>
  <name>EG</name>
  <summary>3D Editor and Game Engine</summary>
  <description>
    <p>EG is a powerful 3D editor and game engine based on Panda3D.</p>
  </description>
  <launchable type="desktop-id">EG.desktop</launchable>
  <url type="homepage">https://your-website.com</url>
  <provides>
    <binary>EG</binary>
  </provides>
</component>
EOF

# 复制图标
for size in 256 128 64; do
    ICON_SRC="$PROJECT_ROOT/icons/app_${size}.png"
    if [ -f "$ICON_SRC" ]; then
        cp "$ICON_SRC" "$APPDIR/usr/share/icons/hicolor/${size}x${size}/apps/EG.png"
    elif [ -f "$PROJECT_ROOT/icons/app.png" ]; then
        # 如果只有一张图，复制到所有尺寸
        cp "$PROJECT_ROOT/icons/app.png" "$APPDIR/usr/share/icons/hicolor/${size}x${size}/apps/EG.png"
        break
    fi
done

# 创建 AppRun
cat > "$APPDIR/AppRun" << 'EOF'
#!/bin/bash
# AppRun for EG

SELF=$(readlink -f "$0")
HERE=${SELF%/*}

# 设置环境变量
export PATH="${HERE}/usr/bin:${PATH}"
export EG_PROJECT_ROOT="${HERE}/usr/lib/EG"
export LD_LIBRARY_PATH="${HERE}/usr/lib/EG:${HERE}/usr/lib:${LD_LIBRARY_PATH}"
export PYTHONPATH="${HERE}/usr/lib/EG:${HERE}/usr/lib/EG/RenderPipelineFile:${PYTHONPATH}"

# 设置 XDG 目录
export XDG_DATA_DIRS="${HERE}/usr/share:${XDG_DATA_DIRS:-/usr/local/share:/usr/share}"

# 切换到项目根目录，确保相对资源路径与 Windows 打包版保持一致
cd "${EG_PROJECT_ROOT}" || exit 1

# 执行主程序
exec "${HERE}/usr/bin/EG" "$@"
EOF
chmod +x "$APPDIR/AppRun"

# 复制 .desktop 和图标到根目录
cp "$APPDIR/usr/share/applications/EG.desktop" "$APPDIR/"
if [ -f "$APPDIR/usr/share/icons/hicolor/256x256/apps/EG.png" ]; then
    cp "$APPDIR/usr/share/icons/hicolor/256x256/apps/EG.png" "$APPDIR/EG.png"
elif [ -f "$APPDIR/usr/share/icons/hicolor/128x128/apps/EG.png" ]; then
    cp "$APPDIR/usr/share/icons/hicolor/128x128/apps/EG.png" "$APPDIR/EG.png"
elif [ -f "$APPDIR/usr/share/icons/hicolor/64x64/apps/EG.png" ]; then
    cp "$APPDIR/usr/share/icons/hicolor/64x64/apps/EG.png" "$APPDIR/EG.png"
fi

log_success "AppDir 准备完成"

# 步骤 5: 创建 AppImage
log_step 5 6 "创建 AppImage..."

cd "$DIST_DIR"

# 下载 appimagetool
APPIMAGETOOL="appimagetool-x86_64.AppImage"
if [ ! -f "$APPIMAGETOOL" ]; then
    log_info "下载 appimagetool..."
    wget -q "https://github.com/AppImage/AppImageKit/releases/download/continuous/appimagetool-x86_64.AppImage" -O "$APPIMAGETOOL" || {
        log_error "下载 appimagetool 失败"
        exit 1
    }
    chmod +x "$APPIMAGETOOL"
    log_success "下载完成"
fi

# 创建 AppImage
APPIMAGE_NAME="EG-${VERSION}-x86_64.AppImage"
log_info "构建 AppImage..."

# 使用 --appimage-extract-and-run 避免 fuse 依赖
ARCH=x86_64 ./"$APPIMAGETOOL" --appimage-extract-and-run "$APPDIR" "$APPIMAGE_NAME" 2>&1 | while read line; do
    echo "  $line"
done

if [ -f "$APPIMAGE_NAME" ]; then
    chmod +x "$APPIMAGE_NAME"
    SIZE=$(du -h "$APPIMAGE_NAME" | cut -f1)
    log_success "AppImage 创建成功: $APPIMAGE_NAME ($SIZE)"
else
    log_error "AppImage 创建失败"
    exit 1
fi

# 可选: 创建 DEB 包
if [ "$BUILD_DEB" = true ]; then
    log_step 5 6 "创建 DEB 包..."
    
    DEB_DIR="$BUILD_DIR/eg_${VERSION}_amd64"
    mkdir -p "$DEB_DIR/DEBIAN"
    mkdir -p "$DEB_DIR/opt/EG"
    mkdir -p "$DEB_DIR/usr/share/applications"
    mkdir -p "$DEB_DIR/usr/share/icons/hicolor/256x256/apps"
    mkdir -p "$DEB_DIR/usr/bin"
    
    # 控制文件
    cat > "$DEB_DIR/DEBIAN/control" << EOF
Package: eg
Version: $VERSION
Section: graphics
Priority: optional
Architecture: amd64
Depends: libgl1, libopenal1, libglu1-mesa, python3 (>= 3.8)
Maintainer: $COMPANY_NAME <support@your-website.com>
Description: EG 3D Editor and Game Engine
 EG is a powerful 3D editor and game engine
 based on Panda3D with advanced rendering.
EOF
    
    # 复制文件
    cp -r "$APPDIR/usr/"* "$DEB_DIR/opt/EG/"
    
    # 创建启动器
    cat > "$DEB_DIR/usr/bin/EG" << EOF
#!/bin/bash
cd /opt/EG
./bin/EG "\$@"
EOF
    chmod +x "$DEB_DIR/usr/bin/EG"
    
    # 复制 desktop 文件和图标
    cp "$APPDIR/usr/share/applications/EG.desktop" "$DEB_DIR/usr/share/applications/"
    if [ -f "$APPDIR/usr/share/icons/hicolor/256x256/apps/EG.png" ]; then
        cp "$APPDIR/usr/share/icons/hicolor/256x256/apps/EG.png" "$DEB_DIR/usr/share/icons/hicolor/256x256/apps/"
    fi
    
    # 构建 deb
    dpkg-deb --build "$DEB_DIR" "$DIST_DIR/eg_${VERSION}_amd64.deb"
    
    if [ -f "$DIST_DIR/eg_${VERSION}_amd64.deb" ]; then
        SIZE=$(du -h "$DIST_DIR/eg_${VERSION}_amd64.deb" | cut -f1)
        log_success "DEB 包创建成功: eg_${VERSION}_amd64.deb ($SIZE)"
    fi
fi

# 步骤 6: 创建 tarball
log_step 6 6 "创建 tarball..."

cd "$BUILD_DIR"

# 创建普通 tarball
TARBALL="$DIST_DIR/EG_${VERSION}_Linux_Portable.tar.gz"
tar -czf "$TARBALL" -C "$APPDIR/usr/lib/EG" .
SIZE=$(du -h "$TARBALL" | cut -f1)
log_success "Tarball 创建成功: EG_${VERSION}_Linux_Portable.tar.gz ($SIZE)"

# ==================== 完成 ====================

echo ""
echo "========================================"
echo -e "${GREEN}  构建完成!${NC}"
echo "========================================"
echo ""
echo -e "${BLUE}输出文件:${NC}"

for file in "$DIST_DIR"/EG-*; do
    if [ -f "$file" ]; then
        name=$(basename "$file")
        size=$(du -h "$file" | cut -f1)
        echo -e "  ${GREEN}✓${NC} $name (${size})"
    fi
done

echo ""
echo -e "${BLUE}输出目录:${NC} $DIST_DIR"
echo ""

# 清理
rm -rf "$APPDIR"
log_info "临时文件已清理"
