#!/bin/bash

function msleep {
  perl -e "select(undef,undef,undef,${1}/1000)"
}

function setBlue {
  echo "${1}" > /sys/devices/leds_ulogo/leds/ulogo_ctrl/subsystem/blue/brightness
}

function setWhite {
  echo "${1}" > /sys/devices/leds_ulogo/leds/ulogo_ctrl/subsystem/white/brightness
}

function removeQueue {
  echo "Removing ${1} from the queue..."
  sed -i "s|^${1}$||g" "/tmp/doled/doled.queue"
}

function doSet {
  setBlue ${1}
  setWhite ${2}
  msleep ${3}
  if [[ ${4} == "lock" ]]; then
    rm -f "/tmp/doled/${lockfilename}.lock"
  fi
}

function doToggle {
  local n

  for ((n=0; n<${7}; n++)); do
    doSet ${1} ${2} ${3}
    doSet ${4} ${5} ${6}
  done
  if [[ ${8} == "lock" ]]; then
    rm -f "/tmp/doled/${lockfilename}.lock"
  fi
}

function doFade {
  local blue
  local white
  local blue_diff
  local white_diff
  local blue_range
  local white range
  local range
  local max_steps_forward
  local max_steps_backward
  local steps_forward
  local steps_backward
  local delay_forward
  local delay_backwards
  local n
  local s

  max_steps_forward=$((${5}/5))
  blue_diff=$((${1}-${3}))
  blue_range=${blue_diff#-}
  white_diff=$((${2}-${4}))
  white_range=${white_diff#-}
  if [[ ${blue_range} == 0 ]] && [[ ${white_range} -gt 0 ]]; then
    steps_forward=$(( white_range < max_steps_forward ? white_range : max_steps_forward ))
  elif [[ ${blue_range} -gt 0 ]] && [[ ${white_range} == 0 ]]; then
    steps_forward=$(( blue_range < max_steps_forward ? blue_range : max_steps_forward ))
  elif [[ ${blue_range} -gt 0 ]] && [[ ${white_range} -gt 0 ]]; then
    range=$(( blue_range < white_range ? blue_range : white_range ))
    steps_forward=$(( range < max_steps_forward ? range : max_steps_forward ))
  else
    steps_forward=${max_steps_forward}
  fi
  delay_forward=$((${5}/steps_forward))
  if [[ ${6} -ge 5 ]]; then
    max_steps_backward=$((${6}/5))
    if [[ ${blue_range} == 0 ]] && [[ ${white_range} -gt 0 ]]; then
      steps_backward=$(( white_range < max_steps_backward ? white_range : max_steps_backward ))
    elif [[ ${blue_range} -gt 0 ]] && [[ ${white_range} == 0 ]]; then
      steps_backward=$(( blue_range < max_steps_backward ? blue_range : max_steps_backward ))
    elif [[ ${blue_range} -gt 0 ]] && [[ ${white_range} -gt 0 ]]; then
      range=$(( blue_range < white_range ? blue_range : white_range ))
      steps_backward=$(( range < max_steps_backward ? range : max_steps_backward ))
    else
      steps_backward=${max_steps_backward}
    fi
    delay_backward=$((${6}/steps_backward))
  fi
  for ((n=0; n<${7}; n++)); do
    for ((s=0; s<${steps_forward}; s++)); do
      blue=$((${1}-(blue_diff*s/(steps_forward-1))))
      white=$((${2}-(white_diff*s/(steps_forward-1))))
      doSet ${blue} ${white} ${delay_forward}
    done
    if [[ ${6} -ge 5 ]]; then
      for ((s=0; s<${steps_backward}; s++)); do
        blue=$((${3}+(blue_diff*s/(steps_backward-1))))
        white=$((${4}+(white_diff*s/(steps_backward-1))))
        doSet ${blue} ${white} ${delay_backward}
      done
    fi
  done
  if [[ ${8} == "lock" ]]; then
    rm -f "/tmp/doled/${lockfilename}.lock"
  fi
}

function doLoop {
  local n
  local i

  for ((n=0; n<${2}; n++)); do
    for ((i=$((index+1)); i<$((index+${1}+1)); i++)); do
      if [[ ${cmds[${i}]} == "set" ]]; then
        #echo "doSet ${opts1[${i}]} ${opts2[${i}]} ${opts3[${i}]}" >> "/tmp/doled/${lockfilename}.errors"
        doSet ${opts1[${i}]} ${opts2[${i}]} ${opts3[${i}]}
      elif [[ ${cmds[${i}]} == "toggle" ]]; then
        #echo "doToggle ${opts1[${i}]} ${opts2[${i}]} ${opts3[${i}]} ${opts4[${i}]} ${opts5[${i}]} ${opts6[${i}]} ${opts7[${i}]}" >> "/tmp/doled/${lockfilename}.errors"
        doToggle ${opts1[${i}]} ${opts2[${i}]} ${opts3[${i}]} ${opts4[${i}]} ${opts5[${i}]} ${opts6[${i}]} ${opts7[${i}]}
      elif [[ ${cmds[${i}]} == "fade" ]]; then
        #echo "doFade ${opts1[${i}]} ${opts2[${i}]} ${opts3[${i}]} ${opts4[${i}]} ${opts5[${i}]} ${opts6[${i}]} ${opts7[${i}]}" >> "/tmp/doled/${lockfilename}.errors"
        doFade ${opts1[${i}]} ${opts2[${i}]} ${opts3[${i}]} ${opts4[${i}]} ${opts5[${i}]} ${opts6[${i}]} ${opts7[${i}]}
#      elif [[ ${cmds[${i}]} == "loop" ]]; then
#        #echo "doLoop ${opts1[${i}]} ${opts2[${i}]}" >> "/tmp/doled/${lockfilename}.errors"
#        doLoop ${opts1[${i}]} ${opts2[${i}]}
      elif [[ ${cmds[${i}]} == "stop" ]]; then
        rm -f "/tmp/doled/${lockfilename}.lock"
        doSet 0 0 5
        removeQueue "${filename}"
      fi
    done
  done
  if [[ ${3} == "lock" ]]; then
    rm -f "/tmp/doled/${lockfilename}.lock"
  fi
}

if [[ -z ${1} ]]; then
  echo "Must give LED sequence file name..." >&2
  echo "Example:" >&2
  echo "./doled.sh filename" >&2
  exit 1
fi

declare filename="${1}"
declare lockfilename="${filename//\//.}"
if [[ ${lockfilename:0:1} == "." ]]; then
  lockfilename="${lockfilename:1}"
fi

mkdir -p "/tmp/doled"
touch "/tmp/doled/doled.queue"

if [[ ! -f "${filename}" ]]; then
  echo "Given LED sequence file name does not exist..." >&2
  exit 2
fi

if [[ ${2} == "remove" ]]; then
  removeQueue ${filename}
  exit 0
fi

if ! grep -q "^${filename}$" "/tmp/doled/doled.queue"; then
  echo "Adding ${filename} to the queue..."
  echo "${filename}" >> "/tmp/doled/doled.queue"
else
  echo "${filename} is already in the queue..."
fi

if [[ -f "/tmp/doled/doled.lock" ]]; then
  echo "doled.sh is already running..."
  exit 3
fi

touch "/tmp/doled/doled.lock"
uled-ctrl off

while [[ $(cat "/tmp/doled/doled.queue" | wc -l) -gt 0 ]]; do
  while read -r filename; do
    [[ "${filename}" =~ ^#.*$ || -z "${filename}" ]] && continue

    lockfilename="${filename//\//.}"
    if [[ ${lockfilename:0:1} == "." ]]; then
      lockfilename="${lockfilename:1}"
    fi

    if [[ ! -f "${filename}" ]]; then
      removeQueue ${filename}
    else

      declare -a cmds
      declare -a opts1
      declare -a opts2
      declare -a opts3
      declare -a opts4
      declare -a opts5
      declare -a opts6
      declare -a opts7
      declare -a jumps
      declare -A jumppoints
      declare -A jumpcount
      declare count=0
      declare errors=0
      declare index=0

      echo "Loading and checking sequence file ${filename}..."
      rm -f "/tmp/doled/${lockfilename}.errors"
      while read -r cmd opt1 opt2 opt3 opt4 opt5 opt6 opt7; do

        ((count++))

        [[ "${cmd}" =~ ^#.*$ || -z "${cmd}" ]] && continue

        if [[ ${cmd,,} == "set" ]]; then
          ## Set a brightness per colour and wait a duration
          ## opt1 = blue value : 0-255 / on / off
          ## opt2 = white value : 0-255 / on / off
          ## opt3 = duration : integer 5-5000 (ms)
          if [[ ${opt1,,} == "on" ]] || [[ ${opt1} -gt 255 ]]; then
            opt1=255
          elif [[ ${opt1,,} == "off" ]] || [[ ${opt1} -lt 0 ]]; then
            opt1=0
          fi
          if [[ ! ${opt1} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt1 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ${opt2,,} == "on" ]] || [[ ${opt2} -gt 255 ]]; then
            opt2=255
          elif [[ ${opt2,,} == "off" ]] || [[ ${opt2} -lt 0 ]]; then
            opt2=0
          fi
          if [[ ! ${opt2} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt2 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ! ${opt3} =~ ^(5000|[1-4][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[5-9])$ ]]; then
            echo "Error at line ${count} : opt3 must be 5-5000" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          opt4=0
          opt5=0
          opt6=0
          opt7=0
        elif [[ ${cmd,,} == "toggle" ]]; then
          ## Toggle between two sets of brightness per colour with a duration for each and a count number of times
          ## opt1 = first blue value : 0-255 / on / off
          ## opt2 = first white value : 0-255 / on / off
          ## opt3 = first duration : integer 5-5000 (ms)
          ## opt4 = second blue value : 0-255 / on / off
          ## opt5 = second white value : 0-255 / on / off
          ## opt6 = second duration : integer 5-5000 (ms)
          ## opt7 = count : 1-256 or omitted
          if [[ ${opt1,,} == "on" ]] || [[ ${opt1} -gt 255 ]]; then
            opt1=255
          elif [[ ${opt1,,} == "off" ]] || [[ ${opt1} -lt 0 ]]; then
            opt1=0
          fi
          if [[ ! ${opt1} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt1 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ${opt2,,} == "on" ]] || [[ ${opt2} -gt 255 ]]; then
            opt2=255
          elif [[ ${opt2,,} == "off" ]] || [[ ${opt2} -lt 0 ]]; then
            opt2=0
          fi
          if [[ ! ${opt2} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt2 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ! ${opt3} =~ ^(5000|[1-4][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[5-9])$ ]]; then
            echo "Error at line ${count} : opt3 must be 5-5000" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ${opt4,,} == "on" ]] || [[ ${opt4} -gt 255 ]]; then
            opt4=255
          elif [[ ${opt4,,} == "off" ]] || [[ ${opt4} -lt 0 ]]; then
            opt4=0
          fi
          if [[ ! ${opt4} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt4 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ${opt5,,} == "on" ]] || [[ ${opt5} -gt 255 ]]; then
            opt5=255
          elif [[ ${opt5,,} == "off" ]] || [[ ${opt5} -lt 0 ]]; then
            opt5=0
          fi
          if [[ ! ${opt5} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt5 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ! ${opt6} =~ ^(5000|[1-4][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[5-9])$ ]]; then
            echo "Error at line ${count} : opt6 must be 5-5000" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ -z ${opt7} ]]; then
            opt7=1
          fi
          if [[ ! ${opt7} =~ ^(25[0-6]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[1-9])$ ]]; then
            echo "Error at line ${count} : opt7 must be 1-256" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
        elif [[ ${cmd,,} == "fade" ]]; then
          ## Fade from a start brightness per colour to an end brightness per colour for a duration time
          ## Optional reverse fade direction for another duration time
          ## Optional count number of fade cycles
          ## opt1 = start blue value : 0-255 / on / off
          ## opt2 = start white value : 0-255 / on / off
          ## opt3 = end blue value : 0-255 / on / off
          ## opt4 = end white value : 0-255 / on / off
          ## opt5 = duration : integer 5-5000 (ms)
          ## opt6 = reverse duration : integer (ms) (optional)
          ## opt7 = count : 1-256 (optional - set opt6 to 0 if using opt7 but not opt 6)
          if [[ ${opt1,,} == "on" ]] || [[ ${opt1} -gt 255 ]]; then
            opt1=255
          elif [[ ${opt1,,} == "off" ]] || [[ ${opt1} -lt 0 ]]; then
            opt1=0
          fi
          if [[ ! ${opt1} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt1 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ${opt2,,} == "on" ]] || [[ ${opt2} -gt 255 ]]; then
            opt2=255
          elif [[ ${opt2,,} == "off" ]] || [[ ${opt2} -lt 0 ]]; then
            opt2=0
          fi
          if [[ ! ${opt2} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt2 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ${opt3,,} == "on" ]] || [[ ${opt3} -gt 255 ]]; then
            opt3=255
          elif [[ ${opt3,,} == "off" ]] || [[ ${opt3} -lt 0 ]]; then
            opt3=0
          fi
          if [[ ! ${opt3} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt3 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ${opt4,,} == "on" ]] || [[ ${opt4} -gt 255 ]]; then
            opt4=255
          elif [[ ${opt4,,} == "off" ]] || [[ ${opt4} -lt 0 ]]; then
            opt4=0
          fi
          if [[ ! ${opt4} =~ ^(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])$ ]]; then
            echo "Error at line ${count} : opt4 must be on, off or 0-255" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ! ${opt5} =~ ^(5000|[1-4][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[5-9])$ ]]; then
            echo "Error at line ${count} : opt5 must be 5-5000" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ -z ${opt6} ]]; then
            opt6=0
          fi
          if [[ ! ${opt6} =~ ^(5000|[1-4][0-9]{3}|[1-9][0-9]{2}|[1-9][0-9]|[5-9]|0)$ ]]; then
            echo "Error at line ${count} : opt6 must be 5-5000, 0 if using opt7 or can be omitted if not using opt7" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ -z ${opt7} ]]; then
            opt7=1
          fi
          if [[ ! ${opt7} =~ ^(25[0-6]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[1-9])$ ]]; then
            echo "Error at line ${count} : opt7 must be 1-256 or omitted" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
        elif [[ ${cmd,,} == "loop" ]]; then
          ## Loop the next number of lines count number of times
          ## opt1 = number of sequential lines to loop : 2-256
          ## opt2 = count : 2-256
          if [[ ! ${opt1} =~ ^(25[0-6]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[2-9])$ ]]; then
            echo "Error at line ${count} : opt1 must be 2-256" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ ! ${opt2} =~ ^(25[0-6]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]|[2-9])$ ]]; then
            echo "Error at line ${count} : opt2 must be 2-256" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          opt3=0
          opt4=0
          opt5=0
          opt6=0
          opt7=0
        elif [[ ${cmd,,} == "stop" ]]; then
          ## no opts as it stops the file
          opt1=0
          opt2=0
          opt3=0
          opt4=0
          opt5=0
          opt6=0
          opt7=0
        elif [[ ${cmd,,} == "restart" ]]; then
          ## no opts as it starts the file back at the beginning
          opt1=0
          opt2=0
          opt3=0
          opt4=0
          opt5=0
          opt6=0
          opt7=0
        elif [[ ${cmd,,} == "label" ]]; then
          ## Defines a jump point. Opt1 is the name of the jump point and must be 2 characters or more and must start with a letter and only contain letters, numbers, hyphens and underscores.
          if [[ ! ${opt1} =~ ^[A-Za-z][A-Za-z0-9_-]+$ ]]; then
            echo "Error at line ${count} : opt1 must be string starting with a letter and containing only letters, digits, hyphens and underscores" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          if [[ -n ${jumppoints[${opt1}]} ]]; then
            echo "Error at line ${count} : opt1 can only be unique once in the sequence" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          opt2=0
          opt3=0
          opt4=0
          opt5=0
          opt6=0
          opt7=0
        elif [[ ${cmd,,} == "jump" ]]; then
          ## Jumps to a jump point. Opt1 is the name of the jump point and must be 2 characters or more and must start with a letter and only contain letters, numbers, hyphens and underscores.
          if [[ ! ${opt1} =~ ^[A-Za-z][A-Za-z0-9_-]+$ ]]; then
            echo "Error at line ${count} : opt1 must be string starting with a letter and containing only letters, digits, hyphens and underscores" >> "/tmp/doled/${lockfilename}.errors"
            ((errors++))
          fi
          opt2=0
          opt3=0
          opt4=0
          opt5=0
          opt6=0
          opt7=0
#        elif [[ ${cmd,,} == "load" ]]; then
#          ## Loads a png to the oled display if opt1="image"
#          ## Loads a sequence of pngs to the oled display if opt1="images"
#        elif [[ ${cmd,,} == "unload" ]]; then
#          ## Blanks out the oled display and stops any sequence started by "load images"
#        elif [[ ${cmd,,} == "var" ]]; then
#          ## Defines a variable
#          ## opt1 is variable name
#          ## opt2 is variable value (default = 0)
#          ## opt3 is variable type (default = int | options are int, bool, float)
#          ## opt4 is variable lower limit value (default = 0)
#          ## opt5 is variable lower limit value (default = 255)
#        elif [[ ${cmd,,} == "inc" ]]; then
#          ## Increments a variable
#          ## opt1 is variable name
#          ## opt2 is the increment value (default = 1)
#        elif [[ ${cmd,,} == "dec" ]]; then
#          ## Decrements a variable
#          ## opt1 is variable name
#          ## opt2 is the decrement value (default = 1)
#        elif [[ ${cmd,,} == "if" ]]; then
#          ## Opens if conditional block
#        elif [[ ${cmd,,} == "elif" ]]; then
#          ## Subsequent if conditional block
#        elif [[ ${cmd,,} == "fi" ]]; then
#          ## Closes if conditional block
#        elif [[ ${cmd,,} == "else" ]]; then
#          ## Aternative to if conditional blocks
#        elif [[ ${cmd,,} == "while" ]]; then
#          ## Opens while conditional loop block
#        elif [[ ${cmd,,} == "elihw" ]]; then
#          ## Closes while conditional loop block
#        elif [[ ${cmd,,} == "until" ]]; then
#          ## Opens until conditional loop block
#        elif [[ ${cmd,,} == "litnu" ]]; then
#          ## Closes until conditional loop block
#        elif [[ ${cmd,,} == "for" ]]; then
#          ## Opens for loop block
#        elif [[ ${cmd,,} == "rof" ]]; then
#          ## Closes for loop block
#        elif [[ ${cmd,,} == "sum" ]]; then
#          ## Do sum (+ - * /) - must be able to support float
#        elif [[ ${cmd,,} == "inv" ]]; then
#          ## Invert a variable. true becomes false, int and float becomes the equivelent value based on distance from lower and upper limit
#        elif [[ ${cmd,,} == "wait" ]]; then
#          ## Pause for a number of milliseconds
#        elif [[ ${cmd,,} == "run" ]]; then
#          ## Runs a sequence from an external sequence file then continues with the current sequence file
#        elif [[ ${cmd,,} == "return" ]]; then
#          ## Returns to the original location of the last jump command and then continues with the sequence
#        elif [[ ${cmd,,} == "" ]]; then
#          ##
        else
          echo "Error at line ${count} : ${cmd,,} is not a valid command" >> "/tmp/doled/${lockfilename}.errors"
          ((errors++))
        fi

        if [[ ${errors} == 0 ]]; then
          cmds+=(${cmd,,})
          opts1+=(${opt1})
          opts2+=(${opt2})
          opts3+=(${opt3})
          opts4+=(${opt4})
          opts5+=(${opt5})
          opts6+=(${opt6})
          opts7+=(${opt7})
          if [[ ${cmd,,} == "label" ]]; then
            jumppoints[${opt1}]=${index}
          fi
          if [[ ${cmd,,} == "jump" ]]; then
            jumpcount[${opt1}]=${count}
            jumps+=(${opt1})
            jumps=($(echo "${jumps}" | tr ' ' '\n' | sort | uniq))
          fi
          ((index++))
        fi

      done < "${filename}"

      for jump in ${jumps[@]}; do
        if [[ -z ${jumppoints[${jump}]} ]]; then
          echo "Error at line ${jumpcount[${jump}]} : Jump point ${jump} is called but is not labelled" >> "/tmp/doled/${lockfilename}.errors"
          ((errors++))
        fi
      done

      if [[ ${errors} -gt 0 ]]; then
        echo "A total of ${errors} were found! Exiting..." >> "/tmp/doled/${lockfilename}.errors"
        removeQueue "${filename}"
      else

        #/sys/devices/leds_ulogo/leds/ulogo_ctrl/subsystem/blue
        #/sys/devices/leds_ulogo/leds/ulogo_ctrl/subsystem/white

        echo "Starting sequence... ${filename}"

        index=0

        while grep -q "^${filename}$" "/tmp/doled/doled.queue" && [[ ${#cmds[@]} -ge ${index} ]]; do

          if [[ ! -f "/tmp/doled/${lockfilename}.lock" ]]; then
            if [[ ${cmds[${index}]} == "set" ]]; then
              touch "/tmp/doled/${lockfilename}.lock"
              #echo "doSet ${opts1[${index}]} ${opts2[${index}]} ${opts3[${index}]} lock &" >> "/tmp/doled/${lockfilename}.errors"
              doSet ${opts1[${index}]} ${opts2[${index}]} ${opts3[${index}]} lock &
              ((index++))
            elif [[ ${cmds[${index}]} == "toggle" ]]; then
              touch "/tmp/doled/${lockfilename}.lock"
              #echo "doToggle ${opts1[${index}]} ${opts2[${index}]} ${opts3[${index}]} ${opts4[${index}]} ${opts5[${index}]} ${opts6[${index}]} ${opts7[${index}]} lock &" >> "/tmp/doled/${lockfilename}.errors"
              doToggle ${opts1[${index}]} ${opts2[${index}]} ${opts3[${index}]} ${opts4[${index}]} ${opts5[${index}]} ${opts6[${index}]} ${opts7[${index}]} lock &
              ((index++))
            elif [[ ${cmds[${index}]} == "fade" ]]; then
              touch "/tmp/doled/${lockfilename}.lock"
              #echo "doFade ${opts1[${index}]} ${opts2[${index}]} ${opts3[${index}]} ${opts4[${index}]} ${opts5[${index}]} ${opts6[${index}]} ${opts7[${index}]} lock &" >> "/tmp/doled/${lockfilename}.errors"
              doFade ${opts1[${index}]} ${opts2[${index}]} ${opts3[${index}]} ${opts4[${index}]} ${opts5[${index}]} ${opts6[${index}]} ${opts7[${index}]} lock &
              ((index++))
            elif [[ ${cmds[${index}]} == "loop" ]]; then
              touch "/tmp/doled/${lockfilename}.lock"
              #echo "doLoop ${opts1[${index}]} ${opts2[${index}]} lock &" >> "/tmp/doled/${lockfilename}.errors"
              doLoop ${opts1[${index}]} ${opts2[${index}]} lock &
              index=$((index+${opts1[${index}]}+1))
            elif [[ ${cmds[${index}]} == "stop" ]]; then
#              rm -f "/tmp/doled/${lockfilename}.lock"
              doSet 0 0 5
              removeQueue "${filename}"
            elif [[ ${cmds[${index}]} == "restart" ]]; then
              rm -f "/tmp/doled/${lockfilename}.lock"
              doSet 0 0 5
              index=0
            elif [[ ${cmds[${index}]} == "label" ]]; then
              if [[ ${jumppoints[${opts1[${index}]}]} != ${index} ]]; then
                echo "Runtime error : label ${opts1[${index}]} has moved to ${index}, expecting ${jumppoints[${opts1[${index}]}]}" >> "/tmp/doled/${lockfilename}.errors"
                rm -f "/tmp/doled/${lockfilename}.lock"
                doSet 0 0 5
                removeQueue "${filename}"
              fi
            elif [[ ${cmds[${index}]} == "jump" ]]; then
              if [[ ! ${jumppoints[${opts1[${index}]}]} =~ ^[0-9]+$ ]]; then
                echo "Runtime error : jump is trying to locate an invalid jumppoint at ${jumppoints[${opts1[${index}]}]}" >> "/tmp/doled/${lockfilename}.errors"
              fi
              index=${jumppoints[${opts1[${index}]}]}
            elif [[ ${index} -ge ${#cmds[@]} ]]; then
              rm -f "/tmp/doled/${lockfilename}.lock"
              doSet 0 0 5
              ((index++))
            fi
          fi

        done
      fi
    fi
    unset cmds
    unset opts1
    unset opts2
    unset opts3
    unset opts4
    unset opts5
    unset opts6
    unset opts7
    unset jumps
    unset jumpcount
    unset jumppoints
  done < "/tmp/doled/doled.queue"
  sed -i '/^$/d' "/tmp/doled/doled.queue"
done

while [[ -f "/tmp/doled/${lockfilename}.lock" ]]; do
  msleep 250
done

doSet 0 0 5
rm -f "/tmp/doled/doled.lock"
