/* CSci 658, Software Language Engineering
   GraphViz Code Generator for the State Machine
   H. Conrad Cunningham

1234567890123456789012345678901234567890123456789012345678901234567890

2018-02-15: (V1) Orignal, borrowing from StaticC_Generator

When instantiated with a valid StateMachine semantic model and
GraphViz Code Generator object, this program generates an appropriate
GraphViz Dot file to generate a graphic representation of Martin
Fowler's State Machine example.

*/

import java.io._

/* Do some limited testing of the State Machine Semantic model.

   Much of the hardcoded test here is the configuration example code
   from Fowler's book.  
*/

object GraphVizCodeGenTest {

  def main(args: Array[String]) {
    println("\nState Machine test beginning.\n")

    // Beginning of Folwer's example configuration code
    val doorClosed  = Event("doorClosed",  'D1CL)
    val drawOpened  = Event("drawOpened",  'D2OP)
    val lightOn     = Event("lightOn",     'L1ON)
    val doorOpened  = Event("doorOpened",  'D1OP)
    val panelClosed = Event("panelClosed", 'PNCL)

    val unlockPanelCmd = Command("unlockPanel", 'PNUL)
    val lockPanelCmd   = Command("lockPanel",   'PNLK)
    val lockDoorCmd    = Command("lockDoor",    'D1LK)
    val unlockDoorCmd  = Command("unlockDoor",  'D1UL)

    val idle                 = new State("idle")
    val activeState          = new State("active")
    val waitingForLightState = new State("waitingForLight")
    val waitingForDrawState  = new State("waitingForDraw")
    val unlockedPanelState   = new State("unlockedPanel")

    val machine = new StateMachine(idle)

    idle.addTransition(doorClosed, activeState)
    idle.addAction(unlockDoorCmd)
    idle.addAction(lockPanelCmd)
    idle.setMachine(machine)

    activeState.addTransition(drawOpened, waitingForLightState)
    activeState.addTransition(lightOn, waitingForDrawState)
    activeState.setMachine(machine)

    waitingForLightState.addTransition(lightOn, unlockedPanelState)
    waitingForLightState.setMachine(machine)

    waitingForDrawState.addTransition(drawOpened, unlockedPanelState)
    waitingForDrawState.setMachine(machine)

    unlockedPanelState.addAction(unlockPanelCmd)
    unlockedPanelState.addTransition(panelClosed, idle)
    unlockedPanelState.addAction(lockDoorCmd)
    unlockedPanelState.setMachine(machine)

    machine.addResetEvents(doorOpened)
    // End of Folwer's example configuration code

    // Try the execution of the model
    val commandsChannel = new CommandChannel
    val control = new Controller(machine,commandsChannel)

    println(control.toString)

    control.handle('D1CL)
    control.handle('L1ON)
    control.handle('D2OP)
    control.handle('PNCL)
    println("\nCommands output:  " + commandsChannel.getOutput)

    // Now try code generation
    println("\nBegin code generation.\n")
    val codegen = new GraphVizCodeGen(machine)
    var outname = "graph.gv"
    if (args.length > 0)
      outname = args(0)
    val outfile = new FileWriter(outname)

    codegen.generate(outfile)

    outfile.close()
    println("\nEnd code generation.\n")

    println("\nState Machine test ending.")
  }
}
