#nullable disable
using CallFlow;
using System;
using System.Linq;
using System.Threading.Tasks;
using TCX.Configuration;
using TCX.PBXAPI;
using System.Collections.Generic;
namespace dummy
{
//this handler plays holiday prompt as specified for destination
public class PlayDestinationHolidayPromptBeforeRouting : ScriptBase<PlayDestinationHolidayPromptBeforeRouting>
{
//reference implementation of trunk routing.
DestinationStruct FindDefaultDestination(ExternalLine trunk, string callerID, string DID)
{
DestinationStruct retval = new();
string[] range;
foreach (var a in trunk.RoutingRules)
{
bool match = (a.Conditions.Condition.Type == RuleConditionType.BasedOnDID &&
(
a.Data == DID
|| (a.Data.StartsWith('*') && DID.EndsWith(a.Data[1..]))
))
||
(
a.Conditions.Condition.Type == RuleConditionType.BasedOnCallerID &&
a.Data.Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)
.Any
(x =>
x == "*"
|| x == callerID
|| x.StartsWith('*') && callerID.EndsWith(x[1..])
|| x.EndsWith('*') && callerID.StartsWith(x[..^1])
|| x.StartsWith('*') && x.EndsWith('*') && callerID.Contains(x[1..^1])
|| ((range = x.Split("-", StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries)).Length == 2 ?
(range[0].Length == callerID.Length && range[1].Length == callerID.Length) && (range[0].CompareTo(callerID) <= 0 && range[1].CompareTo(callerID) >= 0) : false)
)
)
||
(a.Conditions.Condition.Type == RuleConditionType.ForwardAll);
if (match)
{
retval.CopyFrom(a.ForwardDestinations.OfficeHoursDestination);
break;
}
}
return retval;
}
public override async Task<bool> StartAsync()
{
var ps = MyCall.PS as PhoneSystem;
if(MyCall.Caller.DN is ExternalLine externalLine && MyCall.IsInbound) //only from trunk
{
//get the inbound target
var defaultDestination = FindDefaultDestination(externalLine, MyCall.Caller.CallerID, MyCall.Caller.CalledNumber).Internal;
//if the destination is Internal
if (defaultDestination != null)
{
var timeBasedroute = defaultDestination.GetTimeBasedRoutingInfo();
//if destination is currently "on holiday" and holiday prompt is defined, we play it
if (timeBasedroute.reason == CallControlAPI.DivertReason.Holiday)
{
if (!string.IsNullOrWhiteSpace(timeBasedroute.holiday?.HolidayPrompt))
{
await MyCall.AssureMedia()
.ContinueWith(x => MyCall.PlayPrompt(null, [timeBasedroute.holiday?.HolidayPrompt], PlayPromptOptions.Blocked))
.Unwrap();
MyCall.Info($"PromptPlayed");
}
//check the name of active holiday and eventually force the GroupHoursMode
char hDayName1st = (timeBasedroute.holiday?.Name)[0];
Dictionary<char, GroupHoursMode> holidayMode = new Dictionary<char, GroupHoursMode>
{
{ '!', GroupHoursMode.ForceOpened },
{ '/', GroupHoursMode.ForceBreak },
{ '>', GroupHoursMode.ForceHoliday } // holiday is already active, required ???
// required naming of holiday when using ">": ">DestinationType.DestinationNumber|Name of Holiday"
// for example: ">IVR.799|my holiday name" or ">Extension.123|another holiday"
};
if (holidayMode.TryGetValue(hDayName1st, out GroupHoursMode forceMode))
{
// only for the called department
string CalledDepartmentNumber = (defaultDestination.GroupMembership.Where( x => x.IsPrimary == true)).First().Group.Number;
ps.GetAll<Group>()
.Where(x => x.Number.Equals(CalledDepartmentNumber))
.Extract(x => x.AllowCallService)
.Select(x =>
{
try
{
//force office hours until end of holiday
var groupCurrentTime = x.Now(out var utc, out var timezone, out var groupmode);
DateTime endDateTime = new DateTime(timeBasedroute.holiday.YearEnd, timeBasedroute.holiday.MonthEnd, timeBasedroute.holiday.DayEnd).Add(timeBasedroute.holiday.TimeOfEndDate);
x.OverrideExpiresAt = endDateTime;
x.CurrentGroupHours = forceMode;
if(hDayName1st=='>') {
var custOp = $"{(timeBasedroute.holiday?.Name).Split(new char[] { '>', '|' }, StringSplitOptions.RemoveEmptyEntries)[0]}.";
MyCall.Info($"custOP: {custOp}");
var has_valid_destination = DestinationStruct.TryParse(custOp, out var destination_struct);
if (has_valid_destination) {
MyCall.Info($"valid Destination! {destination_struct.External} {destination_struct.Internal} {destination_struct.To}");
defaultDestination.HolidaysRoute = destination_struct;
defaultDestination.Save();
}
}
MyCall.Info($"{x.Name} set to '{x.CurrentGroupHours}' until {x.OverrideExpiresAt}, timezone={timezone}, groupmode={groupmode}");
return x;
}
catch (Exception ex)
{
string errorMessage = ex.ToString();
MyCall.Info($"Error: {errorMessage}");
//just ignore it
return null;
}
}).OfType<Group>().OMSave();
}
}
}
}
return false;//we always return false to continue default trunk routing procedure.
}
}
}