/* SunBatch
 * this program is intended to be called from the Suntan Special
 * Display Monitor or used from command line.
 *
 * Description
 *   SunBatch is used by the Suntan Special to run and monitor sequences.
 *
 *   SunBatch('START, SeqName') starts a sequence
 *   SunBatch('PAUSE') pauses a running sequence
 *   SunBatch('RESUME') resumes a paused sequence
 *   SunBatch('STOP') stops a running or paused sequence
 *   SunBatch('CONTEXT') prints the current context on the command line
 *   SunBatch('PROCESS') starts the background processing of a sequence
 *
 * Copyright (C) 2025 Blonde Guy
 * All Rights Reserved
 */

call InitGlobals

optionline = arg(1)
parse var optionline seqCommand seqParameter

/* use this for debugging
call LogCdi "SunBatch(" || seqCommand || "," seqParameter || ")" */

select
   when seqCommand = 'START' then do
      call StartSequence
   end
   when seqCommand = 'PAUSE' then do
      call PauseSequence
   end
   when seqCommand = 'RESUME' then do
      call ResumeSequence
   end
   when seqCommand = 'STOP' then do
      call StopSequence
   end
   when seqCommand = 'CONTEXT' then do
      call PrintContext
   end
   when seqCommand = 'PROCESS' then do
      call ProcessSequence
   end
   otherwise do
      call LogCdi "SunBatch Error:" arg(1)
   end
end

call Directory originalDir
return

/* initialize global variables from Suntan Special settings */
InitGlobals:

signal on Error
signal on Syntax


Call RxFuncAdd 'SysLoadFuncs', 'RexxUtil', 'SysLoadFuncs'
Call SysLoadFuncs

originalDir = Directory()
cr = d2c(13)
pipeName = '\pipe\suntan'
suntanDir = cdglobal('suntanDir')

/* add current directory to system path if it isn't there */
systemPath = value('PATH',,'OS2ENVIRONMENT')
if right(systemPath,1) \= ';' then do
   systemPath = systemPath || ';'
end
if pos(SuntanDir, systemPath) = 0 then do
  systemPath = systemPath || suntanDir
  call value "PATH", systemPath, "OS2ENVIRONMENT"
end

tempDir = cdglobal('tempDir')
rc = SuntanMkDir(tempDir)
if rc <> 5 then do
   if rc = 0 then do
      call LogCdi "Created temporary directory" tempDir
   end
   else do
      call LogCdi "Error" rc "creating temporary directory" tempDir
   end
end

call Directory suntanDir

contextFile = suntanDir || '\context.dat'
contextBackup = suntanDir || '\context.bak'
pauseFile   = suntanDir || '\Pause.$$$'
stopFile    = suntanDir || '\Stop.$$$'

month.1 = 'Jan'
month.2 = 'Feb'
month.3 = 'Mar'
month.4 = 'Apr'
month.5 = 'May'
month.6 = 'Jun'
month.7 = 'Jul'
month.8 = 'Aug'
month.9 = 'Sep'
month.10= 'Oct'
month.11= 'Nov'
month.12= 'Dec'
return

/* Start Sequence */
StartSequence:

call LogCdi "Starting Sequence" seqParameter || "..."
call SysSleep 5

if stream(contextFile, 'c', 'query exists') <> '' then do
   seqName = linein(contextFile)
   call LogCdi "Sequence" seqParameter "was not started."
   call LogCdi "A sequence is already running:" seqName
   call stream contextFile, 'c', 'close'
   return
end

rc = SysCreateObject('WPProgram','SunBatch','<WP_START>',,
        'EXENAME=' || suntanDir || '\sunbatch.cmd;' ||,
        'OBJECTID=<BG_INSTALLER_BATCH>;' ||,
        'STARTUPDIR=' || suntanDir || ';' ||,
        'PARAMETERS=PROCESS;' ||,
        'NOAUTOCLOSE=YES;MINIMIZED=YES;', 'UpdateIfExists')
if rc = 0 then do
   call LogCdi "Could not create startup folder program object for SunBatch"
end

call CreateContext seqParameter

call LogCdi "!seqbuttons"

address cmd '@ Start /min SunBatch PROCESS'
if rc <> 0 then do
   call LogCdi "Error" rc "Starting SunBatch"
end

return

/* Pause Sequence */
PauseSequence:

if stream(pauseFile, 'c', 'query exists') = '' then do
   call Lineout pauseFile, ''
   call Lineout pauseFile
end
else do
   call LogCdi "Sequence is already paused."
end

call LogCdi "!seqbuttons"

return

/* Resume Sequence */
ResumeSequence:

if stream(pauseFile, 'c', 'query exists') <> '' then do
   call SysFileDelete pauseFile
end
else do
   call LogCdi "Sequence is already resumed."
end

call LogCdi "!seqbuttons"

return

/* Stop Sequence */
StopSequence:

if stream(stopFile, 'c', 'query exists') <> '' then do
   call LogCdi "Sequence Stop has already been requested."
   call LogCdi "!seqbuttons"
   
   address cmd '@ Start /min SunBatch PROCESS'
   if rc <> 0 then do
      call LogCdi "Error" rc "Starting SunBatch"
   end

   return
end

if stream(contextFile, 'c', 'query exists') = '' then do
   call LogCdi "No sequence is running."
   call LogCdi "!seqbuttons"
   return
end

call lineout stopFile, ''
call lineout stopFile

return

/* End Sequence */
EndSequence:

parse arg message
rc = CDPopup(message)

call LogCdi message time()
if stream(pauseFile, 'c', 'query exists') <> '' then do
   call SysFileDelete pauseFile
end
call SetDisplay

/* wait, wait, this is the <BG_INSTALLER_BATCH> object! Ahhhhhh! */
rc = SysDestroyObject('<BG_INSTALLER_BATCH>')
if rc = 0 then do
   call LogCdi "Could not destroy the CD-Batch object"
end
else do
   call LogCdi "CD-Batch object destroyed."
end

return

/* Process Sequence */
ProcessSequence:

call ReadContext
call StartMonitor

call LogCdi "SunBatch version 0.69 started at" date() time()
if wasRunning = 1 then do
   call LogCdi "display monitor was already running."
end

do while context.0 <> 0
   call WaitForResumeOrStop
   if context.0 = 0 then do
      call EndSequence "Sequence ended by user request."
      address cmd 'exit'
      return
   end
   currentSeq = context.1
   currentLine = context.1.L
   currentApp = context.1.S.CurrentLine
   currentParm = context.1.S.CurrentLine.P
   call SetDisplay
   call IncrementContext
   call WriteContext
   call ExecuteLine
end

call EndSequence "Automated installation is complete."
address cmd 'exit'

return

/* Create Context file */
CreateContext:
parse arg sequenceFile

call lineout contextFile, sequenceFile || ';1'
call lineout contextFile

return

/* Read Context file */
ReadContext:

/* if the context file does not exist, set Context.0 to 0 and return */
Context.0 = 0
cfstat = stream(contextFile, 'c', 'query exists')
if cfstat = '' then do
   call LogCdi "File not found:" contextFile
   return
end

ln = 1
do while lines(contextFile)
   ContextLine = linein(contextFile)
   semipos = pos(';', ContextLine)
   if semipos > 0 then do
      Context.ln = left(ContextLine, semipos - 1)
      Context.ln.L = substr(ContextLine, semipos + 1)
   end
   else do
      call LogCdi "Invalid context" ContextLine "found"
      return
   end
   Context.0 = ln
   ln = ln + 1
end
call stream contextFile, 'c', 'close'

if Context.0 = 0 then do
   call LogCdi "No lines found in" contextFile
   return
end

call FillSequenceStem

return

FillSequenceStem:

totallines = 0
do i=1 to context.0
   seqName = context.i   
   ln = 1
   context.i.s.0 = 0
   cfstat = stream(seqName, 'c', 'query exists')
   if cfstat = '' then do
      call LogCdi "Sequence File" i "not found:" seqName
   end
   else do while lines(seqName)
      SeqLine = linein(seqName)
      parse var seqLine appName appParam
      Context.i.S.ln = appName
      Context.i.S.ln.P = appParam
      Context.i.S.0 = ln
      ln = ln + 1
      totallines =  totallines + 1
   end
   call stream seqName, 'c', 'close'
end

return

/* Write Context file */
WriteContext:

address cmd '@copy' contextFile contextBackup '> nul'

call SysFileDelete ContextFile
do i=1 to context.0
   call lineout ContextFile, context.i || ';' || context.i.L
end
if context.0 > 0 then do
   call lineout ContextFile
end

return

/* set display values for GUI */
SetDisplay:

if context.0 = 0 then do
   call LogCdi "!sequence Sequence:"
   call LogCdi "!line Line:"
   call LogCdi "!application Application:"
   call LogCdi "!seqbuttons"
   return
end

sequenceName = Context.1
dotPos = lastpos('.', sequenceName)
if dotPos \= 0 then do
   sequenceName = left(sequenceName, dotPos - 1)
end
ln = Context.1.L
call LogCdi "!sequence Sequence:" sequenceName
call LogCdi "!line Line:" ln "of" Context.1.S.0
call LogCdi "!application Application:" Context.1.S.ln Context.1.S.ln.P
call LogCdi "!seqbuttons"

if Context.1.S.0 <> 0 then do
   nPos = (Context.1.L * 100) / Context.1.S.0
   call LogCdi "!setseqbar" nPos
end

return

/* Increment Context */
IncrementContext:

if context.0 = 0 then do
   call LogCdi "sequence is not running"
   return
end

/* increment the current counter */
context.1.L = context.1.L + 1

/* beyond the last line of current sequence? */
if context.1.L > context.1.S.0 then do
   call LogCdi "Executing last line of sequence" context.1
   if context.0 = 1 then do
      context.0 = 0
      return
   end
   do i=2 to context.0
      ln = i - 1
      context.ln = context.i
      context.ln.L = context.i.L
      context.ln.S.0 = context.i.S.0
      do j=1 to context.i.S.0
         context.ln.S.j = context.i.S.j
         context.ln.S.j.P = context.i.S.j.P
      end
   end
   context.0 = context.0 - 1
end

return

/* Print Context file */
PrintContext:

call ReadContext

if context.0 = 0 then do
   call LogCdi "Context file does not exist."
   return
end

do i = 1 to context.0
   call LogCdi "Sequence" context.i "Line" context.i.L
end

return

/* Start Suntan Special Display Monitor */
StartMonitor:

if rxfuncadd('SysWaitForShell','RexxUtil', 'SysWaitForShell') = 1 then do
   call SysWaitForShell 'DESKTOPPOPULATED'
end

/* start display monitor unless it is already running */
call SysSleep 2
pipestate = stream(pipeName, 'c', 'open')
if left(pipestate, 5) \= 'READY' then do
   rc = SysOpenObject('<BG_SUNTAN_MONITOR>', 'DEFAULT', 'TRUE')
   if rc = 0 then do
      address cmd '@start suntan.exe'
      call LogCdi "Starting suntan.exe from command line."
   end
   
   /* wait for display monitor to be ready */
   say "Waiting for Suntan Special to start..."
   do until left(pipestate, 5) = 'READY'
      call SysSleep 1
      pipestate = stream(pipeName, 'c', 'open')
   end
   wasrunning = 0
end
else do
   wasRunning = 1
end
pipestate = stream(pipeName, 'c', 'close')

return

/* Wait For Resume Or Stop */
WaitForResumeOrStop:

if stream(stopFile, 'c', 'query exists') <> '' then do
   context.0 = 0
   call WriteContext
   call SysFileDelete stopFile
   return
end

if stream(pauseFile, 'c', 'query exists') \= '' then do
   call LogCdi "Sequence is paused" time() date()
   do while stream(pauseFile, 'c', 'query exists') \= ''
      call SysSleep 3
      if stream(stopFile, 'c', 'query exists') <> '' then do
         context.0 = 0
         call WriteContext
         call SysFileDelete stopFile
         return
      end      
   end
   call LogCdi "Sequence is resumed" time() date()
   call ReadContext
end

return

/* Execute Line */
ExecuteLine:

select
   when currentApp = '' then do
      call LogCdi "line" currentLine "is blank"
   end
   when left(currentApp, 1) = ';' then do
      call LogCdi "comment:" substr(currentApp, 2) currentParm
   end
   when left(currentApp, 1) = '!' then do
      call LogCdi "Installation disabled for:" substr(currentApp, 2)
   end
   when abbrev(translate(currentApp), 'EXECUTESEQUENCE', 15) then do
      call ExecuteSequence currentParm
   end
   when abbrev(translate(currentApp), 'EDITSEQUENCE', 12) then do
      call EditSequence currentParm
   end
   when abbrev(translate(currentApp), 'REFRESH', 7) then do
      call ApplicationEd 'REFRESH'
   end
   when left(translate(currentApp), 4) = 'SET ' then do
      parse var currentParm setname '=' setvalue
      if setname = '' | setvalue = '' then do
         call LogCdi "Invalid statement:" currentApp currentParm
      end
      else do
         call LogCdi "Setting" setname || '=' || setvalue
         call SetSetting setname, setvalue
      end
   end
   otherwise do
      call ApplicationEd 'INSTALL' currentApp '(Batch Mode)' currentParm
   end
end

return

/* Execute Sequence */
ExecuteSequence:

parse arg seqName
if stream(seqName, 'c', 'query exists') == '' then do
   call LogCdi "Sequence" seqName "was not found."
   return
end
else do
   call LogCdi "Begin sequence" seqName
end

context.0 = context.0 + 1
do i=context.0 to 2 by -1
   ln = i - 1
   context.i = context.ln
   context.i.L = context.ln.L
end

context.1 = seqName
context.1.L = 1
call WriteContext
call FillSequenceStem

return

/* call the sequence editor and wait */
EditSequence:

if right(translate(currentParm), 4) = '.SEQ' then do
   seqName = currentParm
end
else do
   seqName = currentParm || '.SEQ'
end

call LogCdi "Edit Sequence" seqName
call seqed seqName

return

Syntax:
Error:
call LogCdi "Condition" Condition('c') "was raised"
call LogCdi "SunBatch Error" rc "on line" sigl
if rc <> -1 then do
   call LogCdi ErrorText(rc)
end
return 42
