/* 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) 2019 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
   when seqCommand = 'REFRESH' then do
      call ApplicationEd 'REFRESH'
   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:

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.68 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 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
