// Copyright 2000 by Robert I. Pitts <rip@cs.bu.edu>
// All rights reserved.

dirName = { N: "North", E: "East", S: "South", W: "West" }
maze = new Maze("S...##\n#.#...\n#.##.#\n..#.##\n#...#G\n#.#...")
defChars = maze.getCharsAsStr()
setupMaze()
newChars = maze.getCharsAsStr()

changed = false
var interval
running = null
calls = []
algWin = null
callsWin = null

// Functions for setup.

function setupMaze()
{
  var vals = getURLVars()

  var error = maze.setChars(vals) +
              maze.setDirorder(vals["dirorder"])

  if (error != "")
    alert(
      "Error:\n" + error +
      "\nUsing defaults for erroneous parameters."
    )
}

function setup()
{
  with (document.mazeForm) {
    mazeEntry.value = maze

    for (var i = 0; i < dirEntry.length; i++)
      setDir(dirEntry[i], i, true)

    for (var i = 0; i < runInterval.length; i++)
      if (runInterval[i].checked) {
        interval = runInterval[i].value
        break
      }
  }
}

function setDir(select, which, init)
{
  if (init) {
    for (var i = 0; i < select.options.length; i++)
      if (select.options[i].value == maze.dirorder[which]) {
        select.selectedIndex = i
        break
      }
  } else {
    maze.dirorder[which] = select.options[select.selectedIndex].value
    if (algWin != null && typeof algWin.loaded == "boolean")
      algWin.labelDir(which, dirName[maze.dirorder[which]])
    changed = true
  }
}

// Functions to insert customized parameters in web page.

function insertMaze(mazeStr)
{
  var mz = new CharMatrix(mazeStr)
  var tags = []
  for (var i = 1; i < arguments.length; i++)
    tags[tags.length] = {
      type: "pos",
      x: arguments[i].x,
      y: arguments[i].y,
      start: '<FONT COLOR="#ee0000">',
      end: '</FONT>'
    }
  mz.replaceChars(defChars, newChars)
  document.write("<PRE>" + mz.withTags(tags) + "</PRE>")
}

function insertChar(which)
{
  document.write("<CODE>" + maze.chars[which] + "</CODE>")
}

function insertDir(which)
{
  document.write(dirName[maze.dirorder[which]])
}

function insertCoord(x, y, which)
{
  var pos = coordOf(x, y, which)
  document.write("x=" + pos.x + ", y=" + pos.y)
}

function coordOf(x, y, which)
{
  switch (maze.dirorder[which]) {
    case "N": return {x: x, y: y-1}
    case "E": return {x: x+1, y: y}
    case "S": return {x: x, y: y+1}
    case "W": return {x: x-1, y: y}
  }
}

// Functions to control run of maze.

function resetSearch()
{
  if (running != null) {
    clearTimeout(running)
    running = null
  }

  maze.resetSearch()

  with (document.mazeForm) {
    mazeEntry.value = maze  // redraw
    curx.value = ""
    cury.value = ""
    stepDesc.value = ""
    reachedGoal.value = "No"
  }

  if (algWin != null && typeof algWin.loaded == "boolean") {
    algWin.setXY("", "")
    algWin.unpoint()
  }

  calls = []

  if (callsWin != null && typeof callsWin.loaded == "boolean")
    callsWin.reset()
}

function firstStep()
{
  var error = maze.initSearch()

  if (error != "") {
    alert(
      "Error:\n" + error +
      "\nPlease fix before starting search."
    )
    return false
  }

  oneStep()
  return true
}

function oneStep()
{
  if (!maze.nextStep())
    return

  with (document.mazeForm) {
    switch (maze.state.step) {
      case "R":
        stepDesc.value = "In maze?"
        curx.value = maze.state.x
        cury.value = maze.state.y
        if (algWin != null && typeof algWin.loaded == "boolean")
          algWin.setXY(maze.state.x, maze.state.y)
        calls[calls.length] = "FIND-PATH(x=" + maze.state.x +
                                       " y=" + maze.state.y + ")"
        if (callsWin != null && typeof callsWin.loaded == "boolean")
          callsWin.show(calls)
        break

      case "G":
        stepDesc.value = "Is goal?"
        reachedGoal.value = maze.reachedGoal ? "Yes" : "No"
        break

      case "O":
        stepDesc.value = "Is open?"
        break

      case "M":
        stepDesc.value = "Marking"
        mazeEntry.value = maze
        break

      case 0: // First direction,
      case 1: // 2nd direction...
      case 2:
      case 3:
        stepDesc.value = "Going " + dirName[maze.dirorder[maze.state.step]]
        break

      case "U":
        stepDesc.value = "Unmarking"
        mazeEntry.value = maze
        break

      case "F":
        stepDesc.value = "No path from here"
        break

      case "B":
        stepDesc.value = "Back from " + dirName[maze.dirorder[maze.state.dir]]
        curx.value = maze.state.x
        cury.value = maze.state.y
        if (algWin != null && typeof algWin.loaded == "boolean")
          algWin.setXY(maze.state.x, maze.state.y)
        calls.length--
        if (callsWin != null && typeof callsWin.loaded == "boolean")
          callsWin.show(calls)
        break
    }

    if (maze.noMoreSteps()) {
      stepDesc.value = "Search done!"
      mazeEntry.value = maze
    }
  }

  if (algWin != null && typeof algWin.loaded == "boolean") {
    algWin.unpoint()
    algWin.point(maze.currStep())
  }
}

function runSearch()
{
  if (running == null)
    return
  if (maze.noMoreSteps()) {
    running = null
  } else {
    oneStep()
    running = setTimeout(runSearch, interval)
  }
}

function algWinInit()
{
  document.mazeForm.algCheck.checked = true  // just to be sure

  for (var i = 0; i < maze.dirorder.length; i++)
    algWin.labelDir(i, dirName[maze.dirorder[i]])

  if (!maze.startedSearch())
    return

  with (document.mazeForm)
    algWin.setXY(curx.value, cury.value)

  algWin.point(maze.currStep())
}

function callsWinInit()
{
  document.mazeForm.callsCheck.checked = true  // just to be sure
  callsWin.show(calls)
}

function algWinDone()
{
  document.mazeForm.algCheck.checked = false
}

function callsWinDone()
{
  document.mazeForm.callsCheck.checked = false
}
