<?xml version="1.0" standalone="yes"?>

<%
-- Polycom Configuration File Template
-- We use single quotes to avoid escaping XML's double quotes

-- It is important that the first line be the XML declaration

--[[
	Implemented parameters:
		values = {
			device = {
				adminpassword
				digitmap
				digitmaptimeout
				homepage
				musiconhold
				pcportenable
				registrar
				sntpserver
				timezone
				urldialingenable
				militarytimeenable
				displaylang
			}
	 		regX (where X is a number 1-34) = {
				extension  = EXTEN
				password = string
				forwardall = EXTEN
				forwardallenable = boolean
				forwardbusy = EXTEN (allow URI?)
				forwardbusyenable = boolean
				forwardnoanswer = EXTEN
				forwardnoanswerenable = boolean
				polycomringtone = select
				callwaitingenable = boolean
				scaenable = boolean
			}
			-- Assuming that services will not be nil
			services = {
				callhistoryenable = boolean
				callwaitingenable = boolean
				forwarding = boolean
				hotlinedestination = string
				hotlineenable = boolean
				mailbox = string
				mailcallback = string
				speeddialenable = boolean
				provpollingtime = string
				dndenable = boolean
				softkey1 = boolean
				softkey2 = boolean
				softkey3 = boolean
				softkey4 = boolean
				softkey5 = boolean
				softkey6 = boolean
				softkey7 = boolean
				softkey8 = boolean
				softkey9 = boolean
				softkey10 = boolean
			}
--]]
%>

<dynamicConfig

<% -- Allow the use of device.xxx options (Admin Guide A-30) %>
device.set="1"

<% local values = ... %>

<% 
local function xml_attr (t, v)
	if v ~= nil then
		-- Check for -0, which is invalid for Polycom but fine for Lua
		if (v == 0) then v = "0" end
		-- v could be a string, boolean, or a number
		io.write(table.concat(t, '.') .. '="' .. tostring(v) .. '"\n')
	end
end 
%>

<%
--  we can assume that values.device is not nil since values.device.template is this file

xml_attr({ 'voIpProt.server.1.address' }, values.device.registrar)
xml_attr({ 'mb.main.home' }, values.device.homepage)
xml_attr({ 'voIpProt.SIP.musicOnHold.uri' }, values.device.musiconhold)
xml_attr({ 'dialplan.digitmap.timeOut' }, values.device.digitmaptimeout)
xml_attr({ 'feature.urlDialing.enabled' }, values.device.urldialingenable)

if values.device.pcportenable then
	xml_attr({ 'device.net.etherModePC' }, 'Auto')
else
	xml_attr({ 'device.net.etherModePC' }, 'Disabled')
end
-- apply settings in 'device' parameter above
xml_attr({ 'device.net.etherModePC.set' }, '1')

-- Enable 24-hour Clock Mode
if values.device.militarytimeenable then
	xml_attr({'lcl.datetime.time.24HourClock'}, true)
	for langid=19,1,-1 do
		xml_attr({'lcl.ml.lang.clock.'..langid..'.24HourClock'}, true)
	end
else
	xml_attr({'lcl.datetime.time.24HourClock'}, false)
	for langid=19,1,-1 do
		xml_attr({'lcl.ml.lang.clock.'..langid..'.24HourClock'}, false)
	end
end

-- Set the Display screen language
if values.device.displaylang then
	xml_attr({'lcl.ml.lang'}, values.device.displaylang)
end

-- Override the default admin password of '456'
if values.device.adminpassword then
	xml_attr({ 'device.auth.localAdminPassword' }, values.device.adminpassword)
	xml_attr({ 'device.auth.localAdminPassword.set' }, true)
end

-- Handle SNTP and Time Zone parameters
--   See http://pubs.opengroup.org/onlinepubs/9699919799/basedefs/V1_chap08.html
--     TZ variable, with no leading colon
--   Syntax: stdoffset[dst[offset][,start[/time],end[/time]]]
--   Examples: 'GMT0' 'EST5EDT,M3.2.0,M11.1.0' '<GMT+5>5'
if values.device.sntpserver then
	xml_attr({ 'tcpIpApp.sntp.address' }, values.device.sntpserver)
end

--  Parse time zone variable
posixtz = require('posixtz')
local tz = posixtz.parse(values.device.timezone)

if tz then
	-- convert POSIX sign (W of GMT is '+') to Polycom (E of GMT is '+')
	xml_attr({'tcpIpApp.sntp.gmtOffset'}, -1 * tz.offset.total)

	local function dstrule ( pos )
		local dstprefix = 'tcpIpApp.sntp.daylightSavings'
		local t = tz.dst[pos]
	
		-- Handle explicit hour for DST change
		--  (Polycom doesn't implement explicit min or sec)
		--  (Polycom DST implementation assumes DST change is 1 hour)
		if t.hour then
			xml_attr({ dstprefix, pos, 'time' }, t.hour)
		end

		if t.day then
			if pos == 'start' then
				xml_attr({ dstprefix, 'fixedDayEnable' }, true)
			end
			xml_attr({ dstprefix, pos, 'month' }, t.month)
			xml_attr({ dstprefix, pos, 'date' }, t.day)
		else
			if pos == 'start' then
				xml_attr({ dstprefix, 'fixedDayEnable' }, false)
			end
			xml_attr({ dstprefix, pos, 'month' }, t.month)

			-- POSIX weekday is between 0 (Sun) and 6 (Sat)
			-- Polycom dayOfWeek is 1=Sun, 7=Sat
			xml_attr({ dstprefix, pos, 'dayOfWeek' }, tonumber(t.weekday) + 1)
			
			-- POSIX week from 1 to 5, where 1st,2nd..4th, and 5=last
			if t.week == '5' then
				xml_attr({ dstprefix, pos, 'dayOfWeek.lastInMonth' }, true)
			else
				-- Polycom uses 1, 8, 15, 22 for 1st, 2nd... 4th
				local d = 7 * ( tonumber(t.week) - 1 ) + 1
				xml_attr({ dstprefix, pos, 'date' }, d)
			end
		end

	end
	
	if tz.dst then
		xml_attr({'tcpIpApp.sntp.daylightSavings.enable'}, true)

		dstrule('start')
		dstrule('stop')
	else
		xml_attr({'tcpIpApp.sntp.daylightSavings.enable'}, false)
	end
end

-- Check 'services' params
local enable = {forwarding = false, hotline = false}
if values.services then
	-- set variables so that we don't have to test values.services again
	if not values.services.callhistoryenable then
		xml_attr({ 'feature.callListPlaced.enabled' }, '0')
	end
	if not values.services.callwaitingenable then
		-- only allow one call per line key
		xml_attr({ 'call.callsPerLineKey' }, '1' )
	end
	if values.services.forwarding then
		enable.forwarding = true
	end
	if values.services.hotlineenable and values.services.hotlinedestination then
		enable.hotline = true
		-- Set phone to replace any dialed digits with the hotline destination instead
		xml_attr({ 'dialplan.digitmap' }, 'R[#*0123456789].R'..values.services.hotlinedestination..'R')
		xml_attr({ 'dialplan.applyToUserDial' }, '1')
		xml_attr({ 'dialplan.applyToUserSend' }, '1')
	else
		xml_attr({ 'dialplan.digitmap' }, values.device.digitmap)
	end
	if values.services.mailbox then
		xml_attr({ 'msg.mwi.1.subscribe' }, values.services.mailbox)
		xml_attr({ 'msg.mwi.1.callBackMode' }, "contact")
		if values.services.mailcallback and values.services.mailcallback ~= "" then
			xml_attr({ 'msg.mwi.1.callBack' }, values.services.mailcallback)
		else
			xml_attr({ 'msg.mwi.1.callBack' }, string.gsub(values.services.mailbox, "@.*", ""))
		end
	end
	-- set local contact directory to be readonly or readwrite
	if not values.services.speeddialenable then
		xml_attr({ 'dir.local.contacts.maxNum' }, 0)
	end
	-- Set Provisioning Polling to enable as random starting at the time configured in the provpollingtime param and stopping 59 minutes later
	if values.services.provpollingtime then
		xml_attr({ 'prov.polling.enabled' }, 1)
		xml_attr({ 'prov.polling.mode' }, "random")
		xml_attr({ 'prov.polling.time' }, values.services.provpollingtime)
		xml_attr({ 'prov.polling.timeRandomEnd' }, string.gsub(values.services.provpollingtime, "(%d%d):(%d%d)", "%1:59"))
	end
	-- Set DND on the server-side only, the phone does not perform local DND
	if not values.services.dndenable then
		xml_attr({ 'voIpProt.SIP.serverFeatureControl.dnd' }, '1')
		xml_attr({ 'voIpProt.SIP.serverFeatureControl.localProcessing.dnd' }, '0')
		-- For VVXs DND soft key does not display and the option is removed from the phone menu system at Menu > Settings > Features
		xml_attr({ 'feature.doNotDisturb.enable' }, '0')
	end
	-- Loop through Services Parameter Groups looking for 'softkeyX' params
	for sfkey,sfkey_v in pairs(values.services) do
		local sknum = string.match(sfkey, 'softkey(%d+)')
		if sknum then
			if sfkey_v then
				-- Set this softkey to enable
				xml_attr({ 'softkey', sknum, 'enable' }, '1')
			else
				-- Set this softkey to disable
				xml_attr({ 'softkey', sknum, 'enable' }, '0')
			end
		end
	end
end


-- Loop through Parameter Groups looking for 'reg' params
for pg, pg_t in pairs(values) do
	-- Is it of the form regX ?
	local num = string.match(pg, 'reg(%d+)')
	if num then
		-- set Hotline on all possible registrations if it is configured
		if enable.hotline then
			local d = values.services.hotlinedestination
			if d then
				xml_attr({ 'call.autoOffHook', num, 'enabled' }, '1')
				xml_attr({ 'call.autoOffHook', num, 'protocol' }, 'SIP')
				xml_attr({ 'call.autoOffHook', num, 'contact' }, d)
			end
		end

		-- user part of From URI
		xml_attr({ 'reg', num, 'address' }, pg_t.extension)
		-- SIP authentication parameters
		xml_attr({ 'reg', num, 'auth.userId' }, pg_t.extension)
		xml_attr({ 'reg', num, 'auth.password' }, pg_t.password)
		-- Caller ID string
		xml_attr({ 'reg', num, 'displayName' }, pg_t.callerid)
		-- Ringtone
		if pg_t.polycomringtone then
			xml_attr({ 'reg', num, 'ringType'}, 'ringer'..pg_t.polycomringtone)
		end
		-- Only allow one call in this line key
		if not pg_t.callwaitingenable then
			xml_attr({ 'reg', num, 'callsPerLineKey'}, '1' )
		end
		-- Configure Shared Call Appearance for this line
		if pg_t.scaenable then
			xml_attr({ 'reg', num, 'type'}, 'shared')
		end

		-- From Admin_Guide_UCS_v3.3.0:
		--  "The phone has a flexible call forward/diversion feature for each registration. In all cases, a call will only be diverted if a non-Null contact has been configured."
		if enable.forwarding then
			-- Although not documented,
			-- Polycom phones send special options for
			--  'forward all calls', namely:
			--  reg.x.fwdContact and reg.x.fwdStatus

			-- set forwardall as defined
			xml_attr({ 'reg', num, 'fwdStatus' }, pg_t.forwardallenable)
			xml_attr({ 'reg', num, 'fwdContact' }, pg_t.forwardall)

			-- set forwardnoanswer as defined
			xml_attr({ 'reg', num, 'fwd.noanswer.status' }, pg_t.forwardnoanswerenable)
			xml_attr({ 'reg', num, 'fwd.noanswer.contact' }, pg_t.forwardnoanswer)
			-- we do not use 'divert.noanswer.x.timeout',
			--  because it limits maximum rings *even when* forward-on-noanswer disabled

			-- set forwardbusy as defined
			xml_attr({ 'reg', num, 'fwd.busy.status' }, pg_t.forwardbusyenable)
			xml_attr({ 'reg', num, 'fwd.busy.contact' }, pg_t.forwardbusy)

			-- set forwarddnd as defined
			--xml_attr({ 'divert.dnd', num, 'enabled' }, pg_t.forwarddndenable)
			--xml_attr({ 'divert.dnd', num, 'contact' }, pg_t.forwarddnd)
		else  -- forwarding is not enabled
			-- disable the soft-key menu for forwarding
			xml_attr({ 'divert.fwd', num, 'enabled' }, '0')
		end
	end
end
%>

/>
