-- Dynamic Auto Attendant
-- (C)opyright 2008, R. Marc Lewis <marc@avvatel.com>
-- IRC:  gottafixthat
-- Contributed to the FreeSWITCH project and licenced under the Mozilla Public License v1.1

-- Set our default actions and options
context   = session:getVariable("context")
minDigits = 1
maxDigits = 1
-- How many times will we let them run through the extension prefix dialer?
-- This is for security.  We don't want someone tying up the channel without
-- making them suffer at least a little bit.
maxPrefixRuns = 3
curPrefixRun  = 1

--digitPat  = "(\*|#|\\d)\+"
digitPat  = "*"

aaExtLen    = session:getVariable("aa_ExtLen")
if (aaExtLen == nil) then aaExtLen = 3 end

aaDomain    = session:getVariable("aa_domain")
if (aaDomain == nil) then aaDomain = session:getVariable("domain") end

aaAnnouncement = session:getVariable("aa_announcement")
if (aaAnnouncement == nil) then aaAnnouncement = "" end

aaTimeout      = session:getVariable("aa_timeout")
if (aaTimeout == nil) then aaTimeout = "30" end

aaTimeoutAnnounce = session:getVariable("aa_timeoutannounce")
if (aaTimeoutAnnounce == nil) then aaTimeoutAnnounce = "" end

aaTimeoutAction = session:getVariable("aa_timeoutaction")
if (aaTimeoutAction == nil) then aaTimeoutAction = "hangup" end

aaTimeoutTarget = session:getVariable("aa_timeouttarget")
if (aaTimeoutTarget == nil) then aaTimeoutTarget = "" end

aaInvOptAnnounce = session:getVariable("aa_invoptannounce")
if (aaInvOptAnnounce == nil) then aaInvOptAnnounce = "" end

aaInvOptAction = session:getVariable("aa_invoptaction")
if (aaInvOptAction == nil) then aaInvOptAction = "hangup" end

aaInvOptTarget = session:getVariable("aa_invopttarget")
if (aaInvOptTarget == nil) then aaInvOptTarget = "" end

keyList = { "1", "2", "3", "4", "5", "6", "7", "8", "9", "0", "*", "#" }
dtmfActs = { }
curIDX = 1
for i,v in ipairs(keyList) do 
  --dtmfActs[i] = { dtmf=v, action="invalid", playback=aaInvOptAnnounce, target=aaInvOptTarget }
  -- Load the digit actions from the variables
  dtmfVal = v
  if (dtmfVal == "#") then dtmfVal = "pound" end
  if (dtmfVal == "*") then dtmfVal = "star" end

  tmpAct = session:getVariable("aaDigitAct" .. dtmfVal)
  if (tmpAct ~= nil) then
    dtmf = v
    action = tmpAct

    playback = session:getVariable("aaDigitPlay" .. dtmfVal)
    if (playback == nil) then
      playback = ""
    end

    target = session:getVariable("aaDigitTgt" .. dtmfVal)
    if (target == nil) then
      target = ""
    end

    if (tmpAct == "prefix") then target = v end
    
    dtmfActs[curIDX] = { dtmf=dtmf, action=action, playback=playback, target=target }
    curIDX = curIDX + 1
  end
  --freeswitch.consoleLog("warning", "Index: ".. i .." Value: ".. v .."\n")
end
for i,v in ipairs(dtmfActs) do 
  --keyActs[v] = { action="invalid", playback="invalid.wav" }
  freeswitch.consoleLog("warning", "Index: ".. i .." DTMF: ".. v["dtmf"] .." Action: ".. v["action"] .." Target: ".. v["target"] .."\n")
end

-- extPrefixDial - Takes the first digit that we received and then gets
--                 (aaExtLen - 1) more digits, then attempts to transfer
--                 the call to that extension.
function extPrefixDial(firstDigit)
	digLen = aaExtLen - 1
    if (session:ready() == true) then
        extSuffix = session:getDigits(digLen, "", aaTimeout * 1000)
 		
		if (session:ready() == true) then
			if (#extSuffix == digLen) then 
                session:setVariable("prefix_dial_target", firstDigit .. extSuffix);
                session:execute("execute_extension", firstDigit .. extSuffix .. " XML " .. context)
                if (curPrefixRun == maxPrefixRuns) then
                    session:hangup()
                end
                curPrefixRun = curPrefixRun + 1
			end
		end
    end
end

-- processAction - Given a recording and an action, this function
-- will handle processing the options for that action.
function processAction(sndFile, action, target)
    if (session:ready() == true) then
        if (#sndFile) then
            session:streamFile(sndFile)
        end
        if (session:ready() == true) then
            if (action == "hangup") then
                session:hangup()
            elseif (action == "autoattendant") then
                -- FIXME:  This needs to be a transfer to a special target in the
                -- dialplan that will create a new auto attendant.
                session:execute("transfer", "aa-".. target .. " XML " .. context)
                --session:hangup()
            elseif (action == "repeat") then
                -- Repeat is automatic.
            elseif (action == "prefix") then
                extPrefixDial(target)
            elseif (action == "exten") then
                session:execute("transfer", target .. " XML " .. context)
            elseif (action == "voicemail") then
                session:execute("voicemail", "default ".. aaDomain .." ".. target)
                session:hangup()
            elseif (action == "dialbyname") then
                session:streamFile("/opt/freeswitch/sounds/en/us/jjl/directory/8000/dir-unavailable.wav")
                session:sleep(1000)
            else
                -- Unknown Action.  Log it and continue.
                freeswitch.consoleLog("warning", "Unknown auto attendant action '".. action .."'\n")
            end
        end
    end
end

-- Main Auto Attendant Loop.  Continue looping as long as the seesion is valid
-- or if they bomb out more than three times in a row.
curPass = 1
while (session:ready() == true) do
	-- min_digits, max_digits, max_tries, timeout, terminators, audio_files, bad_input_audio_files, digits_regex
	actionTaken = false
	--digits = session:playAndGetDigits(minDigits, maxDigits, 3, aaTimeout * 1000, " ", aaAnnouncement, aaInvOptAnnounce, digitPat);
	digits = session:read(minDigits, maxDigits, aaAnnouncement, aaTimeout * 1000, "")
	--freeswitch.consoleLog("warning", "Got dtmf: ".. digits .."\n");
    if (#digits < minDigits) then 
 		-- We got no digits, they timed out.
		if (session:ready() == true) then
            actionTaken = true
            freeswitch.consoleLog("warning", "Not enough digits.\n")
            processAction(aaTimeoutAnnounce, aaTimeoutAction, aaTimeoutTarget)
            curPass = curPass + 1
            if (curPass > 3) then 
                freeswitch.consoleLog("warning", "Exiting auto attendant.  Timed out 3 times.")
                session:hangup()
            end
        end
    else
        -- Reset the current pass count
        curPass = 1
    end

    if (session:ready() == true) then
        if (actionTaken == false) then
            for i,v in ipairs(dtmfActs) do
                freeswitch.consoleLog("warning", "Checking " ..digits.. " against "..v["dtmf"].."\n")
                if (digits == v["dtmf"]) then
                    freeswitch.consoleLog("warning", "Found match for digit ".. digits .."\n");
                    actionTaken = true
                    processAction(v["playback"], v["action"], v["target"])
                end
            end
        end
    end

    -- If we get here and no action has been taken, do the invalid option actions
    if (session:ready() == true) then
        if (actionTaken == false) then
            freeswitch.consoleLog("warning", "Invalid option hit.\n")
            processAction(aaInvOptAnnounce, aaInvOptAction, aaInvOptTarget)
        end
    end
end

