@echo off
setlocal EnableDelayedExpansion
REM Run OHOS app and debug on Windows
REM Usage: runDebugOhosApp-Win.bat [options] [PLATFORM] [TARGET_ID]
REM   -M / -m 二选一；都不传时在控制台用 1/2/3 选择。RUNOHOS_NO_MENU=1 则默认 debug。

set "SCRIPT_DIR=%~dp0"
set "PROJECT_ROOT=%~dp0.."
set DEFAULT_PLATFORM=ohosArm64
set DEFAULT_TARGET_ID=127.0.0.1:5555
set DEFAULT_BUNDLE_NAME=com.example.harmonyapp
set DEFAULT_ABILITY_NAME=EntryAbility
set BUNDLE_NAME=%DEFAULT_BUNDLE_NAME%
set ABILITY_NAME=%DEFAULT_ABILITY_NAME%
set BUILD_MODE=debug
set BUILD_MODES_SELECT=
set M_WAS_SET=0
set m_was_set=0
set DEBUG_MODE=attach
set LOCAL_OHOS_PATH=
set PLATFORM=
set TARGET_ID=

:parse
if "%~1"=="" goto done_parse
if /i "%~1"=="-M" (set "BUILD_MODES_SELECT=%~2" & set "M_WAS_SET=1" & shift & shift & goto parse)
if "%~1"=="-m" (set "BUILD_MODE=%~2" & set "m_was_set=1" & shift & shift & goto parse)
if "%~1"=="-b" (set "BUNDLE_NAME=%~2" & shift & shift & goto parse)
if "%~1"=="-a" (set "ABILITY_NAME=%~2" & shift & shift & goto parse)
if "%~1"=="-d" (set "DEBUG_MODE=%~2" & shift & shift & goto parse)
if "%~1"=="-p" (set "LOCAL_OHOS_PATH=%~2" & shift & shift & goto parse)
if "%~1"=="-h" goto show_help
if "!PLATFORM!"=="" (set "PLATFORM=%~1") else if "!TARGET_ID!"=="" (set "TARGET_ID=%~1")
shift
goto parse

:done_parse
if "!PLATFORM!"=="" set "PLATFORM=%DEFAULT_PLATFORM%"
if "!TARGET_ID!"=="" set "TARGET_ID=%DEFAULT_TARGET_ID%"

if "!M_WAS_SET!"=="1" (
  rem BUILD_MODES_SELECT from -M
) else if "!m_was_set!"=="1" (
  set "BUILD_MODES_SELECT=!BUILD_MODE!"
) else (
  call :prompt_debug_build_modes_win
)
if "!BUILD_MODES_SELECT!"=="" set "BUILD_MODES_SELECT=debug"

set "HAS_DEBUG=0"
set "HAS_RELEASE=0"
if /i "!BUILD_MODES_SELECT!"=="debug" set "HAS_DEBUG=1"
if /i "!BUILD_MODES_SELECT!"=="release" set "HAS_RELEASE=1"
if /i "!BUILD_MODES_SELECT!"=="all" set "HAS_DEBUG=1" & set "HAS_RELEASE=1"
if "!HAS_DEBUG!!HAS_RELEASE!"=="00" set "HAS_DEBUG=1" & set "HAS_RELEASE=1"

for /f %%t in ('powershell -NoProfile -Command "[int][double]::Parse((Get-Date -UFormat '%%s'))"') do set START_TIME=%%t

echo Run environment configuration:
echo   - Platform: %PLATFORM%
echo   - Device: %TARGET_ID%
echo   - Build modes:
if "!HAS_DEBUG!"=="1" echo     debug
if "!HAS_RELEASE!"=="1" echo     release
echo   - Debug mode: %DEBUG_MODE%
echo   - Bundle: %BUNDLE_NAME%
echo   - Ability: %ABILITY_NAME%
if not "!LOCAL_OHOS_PATH!"=="" echo   - External OHOS path: !LOCAL_OHOS_PATH!
echo ------------------------------------------------------------

if not "!OHOS_SDK_HOME!"=="" (
  set "SDK_HOME=!OHOS_SDK_HOME!"
) else (
  if exist "C:\Program Files\Huawei\DevEco Studio" (
    set "SDK_HOME=C:\Program Files\Huawei\DevEco Studio"
  ) else if exist "D:\Program Files\Huawei\DevEco Studio" (
    set "SDK_HOME=D:\Program Files\Huawei\DevEco Studio"
  ) else (
    echo Error: DevEco Studio not found. Set OHOS_SDK_HOME or install to default path.
    exit /b 1
  )
)
echo DevEco Studio Path: !SDK_HOME!
echo Checking environment configuration...

set "MIN_VERSION=6.0.0"
set "PRODUCT_INFO=!SDK_HOME!\product-info.json"
if exist "!PRODUCT_INFO!" (
  for /f "tokens=*" %%v in ('powershell -NoProfile -Command "(Get-Content '!PRODUCT_INFO!' ^| ConvertFrom-Json).version"') do set "CURRENT_VERSION=%%v"
) else (
  echo Warning: product-info.json not found, skipping version check.
  set "CURRENT_VERSION=unknown"
)

if not "!CURRENT_VERSION!"=="unknown" (
  echo Current DevEco version: !CURRENT_VERSION!
  echo Minimum required version: !MIN_VERSION!
  for /f "tokens=1,2 delims=." %%a in ("!CURRENT_VERSION!") do (set "CUR_MAJOR=%%a" & set "CUR_MINOR=%%b")
  for /f "tokens=1,2 delims=." %%a in ("!MIN_VERSION!") do (set "REQ_MAJOR=%%a" & set "REQ_MINOR=%%b")
  if !CUR_MAJOR! lss !REQ_MAJOR! (
    echo Error: DevEco version is too low!
    exit /b 5
  )
  if !CUR_MAJOR! equ !REQ_MAJOR! if !CUR_MINOR! lss !REQ_MINOR! (
    echo Error: DevEco version is too low!
    exit /b 5
  )
  echo DevEco version meets requirements ^(!CURRENT_VERSION!^)
)

set "HDC_BIN=!SDK_HOME!\sdk\default\openharmony\toolchains\hdc.exe"
set "DEVECO_SDK_HOME=!SDK_HOME!\sdk"
set "PATH=!SDK_HOME!\tools\node;!SDK_HOME!\tools\ohpm\bin;!SDK_HOME!\tools\hvigor\bin;!DEVECO_SDK_HOME!;!PATH!"

if not exist "!HDC_BIN!" (
  echo Error: hdc not found at !HDC_BIN!
  exit /b 1
)

if not "!LOCAL_OHOS_PATH!"=="" (
  set "HARMONY_APP_DIR=!LOCAL_OHOS_PATH!"
) else (
  set "HARMONY_APP_DIR=!PROJECT_ROOT!\harmonyApp"
)

if not exist "!HARMONY_APP_DIR!" (
  echo Error: harmonyApp directory not found: !HARMONY_APP_DIR!
  exit /b 4
)

cd /d "!PROJECT_ROOT!"
echo Project root: !CD!

if "!HAS_DEBUG!"=="1" (
  set "BUILD_MODE=debug"
  call :debug_one_mode
  if errorlevel 1 exit /b 1
)
if "!HAS_RELEASE!"=="1" (
  set "BUILD_MODE=release"
  call :debug_one_mode
  if errorlevel 1 exit /b 1
)

echo.
echo All selected build modes finished.
exit /b 0

:debug_one_mode
echo.
echo ============================================================
echo  buildMode=!BUILD_MODE!
echo ============================================================
"!HDC_BIN!" -t !TARGET_ID! shell aa force-stop !BUNDLE_NAME! 2>nul

echo Working path: !CD!
echo Building OpenHarmony ^(!PLATFORM!^)...

if "!PLATFORM!"=="ohosArm64" (
  if "!BUILD_MODE!"=="release" (
    if not "!LOCAL_OHOS_PATH!"=="" (
      call gradlew.bat :composeApp:publishReleaseBinariesToHarmonyApp -PharmonyAppPath="!LOCAL_OHOS_PATH!"
    ) else (
      call gradlew.bat :composeApp:publishReleaseBinariesToHarmonyApp
    )
  ) else (
    if not "!LOCAL_OHOS_PATH!"=="" (
      call gradlew.bat :composeApp:publishDebugBinariesToHarmonyApp -PharmonyAppPath="!LOCAL_OHOS_PATH!"
    ) else (
      call gradlew.bat :composeApp:publishDebugBinariesToHarmonyApp
    )
  )
) else if "!PLATFORM!"=="ohosX86_64" (
  if "!BUILD_MODE!"=="release" (
    if not "!LOCAL_OHOS_PATH!"=="" (
      call gradlew.bat :composeApp:publishReleaseBinariesToHarmonyApp -PharmonyAppPath="!LOCAL_OHOS_PATH!"
    ) else (
      call gradlew.bat :composeApp:publishReleaseBinariesToHarmonyApp
    )
  ) else (
    if not "!LOCAL_OHOS_PATH!"=="" (
      call gradlew.bat :composeApp:publishDebugBinariesToHarmonyApp -PharmonyAppPath="!LOCAL_OHOS_PATH!"
    ) else (
      call gradlew.bat :composeApp:publishDebugBinariesToHarmonyApp
    )
  )
) else (
  echo Error: Unsupported platform '!PLATFORM!'
  exit /b 4
)

if errorlevel 1 exit /b 1

for /f %%t in ('powershell -NoProfile -Command "[int][double]::Parse((Get-Date -UFormat '%%s'))"') do set HAP_START_TIME=%%t

cd /d "!HARMONY_APP_DIR!"
echo Switched to harmonyApp directory: !CD!
echo Running ohpm and Hvigor ^(buildMode=!BUILD_MODE!^)...

call ohpm install --all
if errorlevel 1 (echo ohpm install failed & exit /b 1)

call node "!SDK_HOME!\tools\hvigor\bin\hvigorw.js" --sync -p product=default -p buildMode=!BUILD_MODE! --analyze=normal --parallel --incremental --daemon
if "!BUILD_MODE!"=="release" (
  call node "!SDK_HOME!\tools\hvigor\bin\hvigorw.js" --mode module -p module=entry -p product=default -p buildMode=release -p requiredDeviceType=phone assembleHap compileNative --analyze=normal --parallel --incremental --daemon
) else (
  call node "!SDK_HOME!\tools\hvigor\bin\hvigorw.js" --mode module -p module=entry@default -p product=default -p buildMode=debug -p requiredDeviceType=phone assembleHap --analyze=normal --parallel --incremental --daemon
)
if errorlevel 1 (echo Hvigor build failed & exit /b 1)

set "HAP_DIR=entry\build\default\outputs\default"
set "SIGNED_HAP=entry-default-signed.hap"
set "HAP_FILE=!HAP_DIR!\!SIGNED_HAP!"

if not exist "!HAP_FILE!" (
  echo Error: Signed HAP package not found: !HAP_FILE!
  exit /b 6
)

set "DEVICE_FOUND="
for /f "delims=" %%i in ('"!HDC_BIN!" list targets 2^>nul') do echo %%i | findstr /C:"!TARGET_ID!" >nul && set "DEVICE_FOUND=1"
if not defined DEVICE_FOUND (
  echo Error: Device !TARGET_ID! is offline!
  exit /b 5
)

echo Pushing debug components and installing HAP...
set "REMOTE_HAP_DIR=/data/local/tmp/debug_install"
set "REMOTE_HAP_PATH=!REMOTE_HAP_DIR!/!SIGNED_HAP!"
"!HDC_BIN!" -t !TARGET_ID! shell mkdir -p !REMOTE_HAP_DIR!
"!HDC_BIN!" -t !TARGET_ID! file send "!HAP_FILE!" !REMOTE_HAP_DIR!

"!HDC_BIN!" -t !TARGET_ID! shell bm install -p "!REMOTE_HAP_PATH!" 2>nul
if errorlevel 1 (
  echo Reinstall: uninstall then install again...
  "!HDC_BIN!" -t !TARGET_ID! shell bm uninstall -n !BUNDLE_NAME! 2>nul
  timeout /t 5 /nobreak >nul
  "!HDC_BIN!" -t !TARGET_ID! shell bm install -p "!REMOTE_HAP_PATH!"
  timeout /t 5 /nobreak >nul
)

"!HDC_BIN!" -t !TARGET_ID! shell rm -rf !REMOTE_HAP_DIR!
timeout /t 1 /nobreak >nul
echo Launching app and starting debug listener...
if "!DEBUG_MODE!"=="debug" (
  echo   Debug mode, starting with -D flag
  "!HDC_BIN!" -t !TARGET_ID! shell aa start -a !ABILITY_NAME! -b !BUNDLE_NAME! -D
) else (
  echo   Attach mode, starting without -D flag
  "!HDC_BIN!" -t !TARGET_ID! shell aa start -a !ABILITY_NAME! -b !BUNDLE_NAME!
)

for /f %%t in ('powershell -NoProfile -Command "[int][double]::Parse((Get-Date -UFormat '%%s'))"') do set END_TIME=%%t
"!HDC_BIN!" -t !TARGET_ID! shell rm -rf /data/local/tmp/debugserver/lldb-server
"!HDC_BIN!" -t !TARGET_ID! shell mkdir -p /data/local/tmp/debugserver
"!HDC_BIN!" -t !TARGET_ID! file send "!SDK_HOME!\sdk\default\hms\native\lldb\aarch64-linux-ohos\lldb-server" /data/local/tmp/debugserver/
"!HDC_BIN!" -t !TARGET_ID! shell chmod 755 /data/local/tmp/debugserver/lldb-server

set /a COUNT=0
:wait_pid_dbg
set "APP_PID="
for /f "tokens=1" %%i in ('"!HDC_BIN!" -t !TARGET_ID! shell pidof !BUNDLE_NAME! 2^>nul') do set "APP_PID=%%i"
if not "!APP_PID!"=="" goto got_pid_dbg
timeout /t 1 /nobreak >nul
set /a COUNT+=1
if !COUNT! lss 25 goto wait_pid_dbg
echo Error: App did not start within expected time
exit /b 1
:got_pid_dbg

echo App started (PID: !APP_PID!)
"!HDC_BIN!" -t !TARGET_ID! shell aa attach -b !BUNDLE_NAME!
"!HDC_BIN!" -t !TARGET_ID! shell aa process -a !ABILITY_NAME! -b !BUNDLE_NAME! -D "/data/local/tmp/debugserver/lldb-server platform --listen unix-abstract:///lldb-server/platform.sock"

echo ------------------------------------------------------------
echo Round completed ^(buildMode=!BUILD_MODE!^)
echo   - Bundle: !BUNDLE_NAME!
echo   - PID: !APP_PID!
echo   - Device: !TARGET_ID!
set /a ELAPSED=!HAP_START_TIME!-!START_TIME!
set /a MINUTES=!ELAPSED!/60
set /a SECONDS=!ELAPSED!%%60
echo   - SO build time ^(from script start^): !MINUTES!m!SECONDS!s ^(!ELAPSED!s^)
set /a ELAPSED=!END_TIME!-!HAP_START_TIME!
set /a MINUTES=!ELAPSED!/60
set /a SECONDS=!ELAPSED!%%60
echo   - HAP package and push ^(this round^): !MINUTES!m!SECONDS!s ^(!ELAPSED!s^)
echo Note: connect LLDB after each round; last round is final install on device.
echo ------------------------------------------------------------

cd /d "!PROJECT_ROOT!"
exit /b 0

:prompt_debug_build_modes_win
if /i "!RUNOHOS_NO_MENU!"=="1" (
  set "BUILD_MODES_SELECT=debug"
  exit /b 0
)
echo.
echo 请选择构建类型（输入数字后回车）:
echo   1 = 仅 debug
echo   2 = 仅 release
echo   3 = debug + release
set "BMENU="
set /p "BMENU=请输入 1 / 2 / 3 [默认 1]: "
if "!BMENU!"=="" set "BMENU=1"
if "!BMENU!"=="1" set "BUILD_MODES_SELECT=debug" & exit /b 0
if "!BMENU!"=="2" set "BUILD_MODES_SELECT=release" & exit /b 0
if "!BMENU!"=="3" set "BUILD_MODES_SELECT=all" & exit /b 0
echo 无效输入，使用默认 1（debug）
set "BUILD_MODES_SELECT=debug"
exit /b 0

:show_help
echo Usage: %~nx0 [options] [PLATFORM] [TARGET_ID]
echo.
echo Options:
echo   -M MODES   debug ^| release ^| all（与 -m 二选一）
echo   -m MODE    仅 debug 或 release（传了则不再弹出菜单）
echo   -b BUNDLE   Set bundle name
echo   -a ABILITY  Set Ability name
echo   -d MODE     Debug attach: debug or attach ^(default attach^)
echo   -p PATH     External OHOS project path
echo   -h          Show help
echo.
echo Examples:
echo   %~nx0 ohosArm64 127.0.0.1:5555
echo   %~nx0 -M all
echo   %~nx0 -M release
echo   %~nx0 -m release
exit /b 0
