:: This batch file handles managing an Erlang node as a Windows service.
::
:: Commands provided:
::
:: * install - install the release as a Windows service
:: * start - start the service and Erlang node
:: * stop - stop the service and Erlang node
:: * restart - run the stop command and start command
:: * uninstall - uninstall the service and kill a running node
:: * ping - check if the node is running
:: * ctl - run management commands
:: * console - start the Erlang release in a `werl` Windows shell
:: * attach - connect to a running node and open an interactive console
:: * remote_console - same as attach
:: * list - display a listing of installed Erlang services
:: * usage - display available commands

:: Set variables that describe the release
@set rel_name=emqx
@set rel_vsn=5.3.2
@set REL_VSN=%rel_vsn%
@set erts_vsn=13.2.2.4
@set erl_opts=

@set script=%~n0

@set EPMD_ARG=-start_epmd false -epmd_module ekka_epmd -proto_dist ekka
@set ERL_FLAGS=%EPMD_ARG%

:: Discover the release root directory from the directory
:: of this script
@set script_dir=%~dp0
@for %%A in ("%script_dir%\..") do @(
  set rel_root_dir=%%~fA
)

:: If release dir has space, change dir
@if not "%rel_root_dir%"=="%rel_root_dir: =%" (
    @chdir /d "%rel_root_dir%"
    @set rel_root_dir=.
)

@set "erts_dir=%rel_root_dir%\erts-%erts_vsn%"
@set "rootdir=%rel_root_dir%"
@set "rel_dir=%rel_root_dir%\releases\%rel_vsn%"
@set "RUNNER_ROOT_DIR=%rel_root_dir%"
:: hard code etc dir
@set "EMQX_ETC_DIR=%rel_root_dir%\etc"
@set "EMQX_LOG_DIR=%rel_root_dir%\log"
@set "etc_dir=%rel_root_dir%\etc"
@set "lib_dir=%rel_root_dir%\lib"
@set "emqx_conf=%etc_dir%\emqx.conf"

@set "boot_file_name=%rel_dir%\start"
@set "service_name=%rel_name%_%rel_vsn%"
@set "bindir=%erts_dir%\bin"
@set progname=erl.exe
@set "clean_boot_file_name=%rel_dir%\start_clean"
@set "erlsrv=%bindir%\erlsrv.exe"
@set "escript=%bindir%\escript.exe"
@set "werl=%bindir%\werl.exe"
@set "erl_exe=%bindir%\erl.exe"
@set "nodetool=%rel_root_dir%\bin\nodetool"
@set HOCON_ENV_OVERRIDE_PREFIX=EMQX_
@set node_type=-name
@set schema_mod=emqx_conf_schema
:: no advanced DB backend for Windows
@set EMQX_NODE__DB_BACKEND=mnesia
@set EMQX_NODE__DB_ROLE=core

:: Write the erl.ini file to set up paths relative to this script
@call :write_ini

:: If a start.boot file is not present, copy one from the named .boot file
@if not exist "%rel_dir%\start.boot" (
  copy "%rel_dir%\%rel_name%.boot" "%rel_dir%\start.boot" >nul
)

@set conf_path="%etc_dir%\emqx.conf"

@for /f "usebackq tokens=1,2 delims==" %%a in (`"%escript% %nodetool% hocon -s %schema_mod% -c %conf_path% multi_get node.name node.cookie node.data_dir"`) do @(
  if "%%a"=="node.name" set node_name=%%b
  if "%%a"=="node.cookie" set node_cookie=%%b
  if "%%a"=="node.data_dir" set data_dir=%%b
)

@set data_dir=%data_dir:"=%
:: remove trailing /
@if %data_dir:~-1%==/ SET data_dir=%data_dir:~0,-1%
:: remove trailing \
@if %data_dir:~-1%==\ SET data_dir=%data_dir:~0,-1%

@set abs_data_dir=%rel_root_dir%\%data_dir%
@if exist %abs_data_dir% (
  @set data_dir=%abs_data_dir%
)

@if not exist %data_dir%\ (
  @echo ERROR: data_dir %data_dir% does not exist
  @goto :eof
)

@if "%1"=="install" @goto install
@if "%1"=="uninstall" @goto uninstall
@if "%1"=="start" @goto start
@if "%1"=="stop" @goto stop
@if "%1"=="restart" @call :stop && @goto start
@if "%1"=="console" @goto console
@if "%1"=="ping" @goto ping
@if "%1"=="ctl" @goto ctl
@if "%1"=="list" @goto list
@if "%1"=="attach" @goto attach
@if "%1"=="remote_console" @goto attach
@if "%1"=="" @goto usage
@echo Unknown command: "%1"

@goto :eof

:create_mnesia_dir
@set create_dir_cmd=%escript% %nodetool% mnesia_dir "%data_dir%\mnesia" %node_name%
@for /f "delims=" %%Z in ('%%create_dir_cmd%%') do @(
  set mnesia_dir=%%Z
)
@goto :eof

:: get the current time with hocon
:get_cur_time
@for /f "usebackq tokens=1-6 delims=." %%a in (`"%escript% %nodetool% hocon now_time"`) do @(
  set now_time=%%a.%%b.%%c.%%d.%%e.%%f
)
@goto :eof

:generate_app_config
@call :get_cur_time
@%escript% %nodetool% hocon -v -t %now_time% -s %schema_mod% -c "%etc_dir%\emqx.conf" -d "%data_dir%\configs" generate
@set generated_config_args=-config "%data_dir%\configs\app.%now_time%.config" -args_file "%data_dir%\configs\vm.%now_time%.args"
:: create one new line
@echo.>>"%data_dir%\configs\vm.%now_time%.args"
:: write the node type and node name in to vm args file
@echo %node_type% %node_name%>>"%data_dir%\configs\vm.%now_time%.args"
@goto :eof

:: Write the erl.ini file
:write_ini
@set "erl_ini=%erts_dir%\bin\erl.ini"
@set converted_bindir=%bindir:\=\\%
@set converted_rootdir=%rootdir:\=\\%
@echo [erlang] > "%erl_ini%"
@echo Bindir=%converted_bindir% >> "%erl_ini%"
@echo Progname=%progname% >> "%erl_ini%"
@echo Rootdir=%converted_rootdir% >> "%erl_ini%"
@goto :eof

:: Display usage information
:usage
@echo usage: %~n0 ^(install^|uninstall^|start^|stop^|restart^|console^|ping^|ctl^|list^|remote_console^|attach^)
@goto :eof

:: Install the release as a Windows service
:: or install the specified version passed as argument
:install
@call :create_mnesia_dir
@call :generate_app_config
:: Install the service
@set args="-boot %boot_file_name% %generated_config_args% -mnesia dir '%mnesia_dir%'"
@set description=EMQX node %node_name% in %rootdir%
@if "" == "%2" (
  %erlsrv% add %service_name% %node_type% "%node_name%" -on restart -c "%description%" ^
           -i "emqx" -w "%rootdir%" -m %erl_exe% -args %args% ^
           -st "init:stop()."
  sc config emqx start=delayed-auto
)
@goto :eof

:: Uninstall the Windows service
:uninstall
@%erlsrv% remove %service_name%
@goto :eof

:: Start the Windows service
:start
:: window service?
:: @%erlsrv% start %service_name%
@call :create_mnesia_dir
@call :generate_app_config
@set args=-detached %generated_config_args% -mnesia dir '%mnesia_dir%'
@echo off
cd /d "%rel_root_dir%"
@echo on
@start "%rel_name%" %werl%  -mode embedded -boot "%boot_file_name%" %args%
@goto :eof

:: Stop the Windows service
:stop
:: window service?
:: @%erlsrv% stop %service_name%
@%escript% %nodetool% %node_type% %node_name% -setcookie %node_cookie% stop
@goto :eof

:: Start a console
:console
@set "EMQX_LOG__CONSOLE_HANDLER__ENABLE=true"
@set "EMQX_LOG__FILE_HANDLERS__DEFAULT__ENABLE=false"
@call :create_mnesia_dir
@call :generate_app_config
@set args=%generated_config_args% -mnesia dir '%mnesia_dir%'
@echo off
cd /d %rel_root_dir%
@echo on
%erl_exe% -mode embedded -boot "%boot_file_name%" %args%
@goto :eof

:: Ping the running node
:ping
@%escript% %nodetool% ping %node_type% "%node_name%" -setcookie "%node_cookie%"
@goto :eof

:: ctl to execute management commands
:ctl
@for /f "usebackq tokens=1*" %%i in (`echo %*`) DO @ set params=%%j
@%escript% %nodetool% %node_type% "%node_name%" -setcookie "%node_cookie%" rpc_infinity emqx_ctl run_command %params%
@goto :eof

:: List installed Erlang services
:list
@%erlsrv% list %service_name%
@goto :eof

:: Attach to a running node
:attach
%erl_exe% -hidden -remsh "%node_name%" -boot "%clean_boot_file_name%" "%node_type%" "remsh_%node_name%" -setcookie "%node_cookie%"
@goto :eof
