{---------------------------------------------------------------------------------
Unit:                  msg-cast-utils.pas
Purpose:               Provides supporting functions and constants
                       for msgcast script.

----------------------------------------------------------------------------------}
{uses Swift, SQLDB}


// Enumerated Types
type
  TValidateReturn = (vrValidated, vrBadPassword, vrBadExten, vrNotActive, vrNotFound, vrConnectError,
    vrNoRowset);

// Scalar constants
const PROMPT_TIMEOUT = 15000;
const PROMPT_CHANCES = 3;

// String constants
const PROMPT_INTRO = 'This is the message broadcast system.  You may dial 9 at any time to exit. ' +
  'I will ask you a series of questions in order to complete the message broadcast.  Please stand by.';
const PROMPT_ERROR = 'You have chosen an incorrect value.  Please try again.';
const PROMPT_ERROR_GIVEUP = 'You have failed to make an acceptable choice.  Cancelling the operation.';
const PROMPT_TOCALL = 'Please enter full telephone number to the party that you would like to broadcast ' +
  'a message to.';
const PROMPT_RETRIES = 'Aside from the initial attempt\, how many attempts would you like to make?';
const PROMPT_RINGTIME = 'Please enter the number of seconds to let the line ring when attempting the call.';
const PROMPT_RETRYTIME = 'Please enter the number of seconds to wait before attempting a failed broadcast ' +
  'call';
const PROMPT_RECORD = 'After the beep\, please record your message';
const PROMPT_VALUE = 'You entered ';
const PROMPT_CONFIRM = 'If this is the correct value\, please press 1.  If it is not the correct value\, ' +
  'please press 0';
const PROMPT_PASSCODE = 'Please enter your 4 digit passcode.';
const PROMPT_EXTEN = 'In order to use this service\, you must verify who you are.  ' +
  'Please enter your extension number followed by number sign';
const PROMPT_VALIDATING = 'Thank you.  Please wait while I validate your credentials.';
const PROMPT_BADEXTEN = 'The extension that you entered was not found in the system';
const PROMPT_BADPASSCODE = 'The pass code that you entered was not valid.';
const PROMPT_FAILURE = 'Validation against our database has failed.  Now exiting back to main menu.';

// context to have the call come back into
const TECHNOLOGY = 'SIP/axVoice/';
const AST_CONTEXT = 'broadcast-return';
const AST_EXTENSION = 's';
const AST_PRIORITY = '1';


// Simple record structure to hold values solicited from the caller.
type
TBroadcastMsg = record
  Channel: string;
  Retries: integer;
  RingTime: integer;
  SecondsBetweenTries: integer;
  Context: string;
  Extension: string;
  Priority: string;
  SetVar: string;
  end;

// Record structure to hold user info
type
  TUser = record
  UserID: string;
  UserFirst: string;
  UserLast: string;
  IsAdmin: Boolean;
  Exten: string;
  end;


{********************************
function CheckResponse
Verifies a a response from the caller against passed in parameter values
********************************}
function CheckResponse(AChoice: string; AMax, ALen: integer): boolean;
var
iNum          : integer;
begin
if (AChoice = '') then
  begin
  result := false;
  exit;
  end;

if (AMax > 0) then
  begin
  iNum := StrToInt(AChoice);
  result := ((iNum <= AMax) AND (length(AChoice) <= ALen));
  end
else
  result := (AChoice <> '');

end;

{********************************
function GetResponse
Plays a prompt to the caller and retrieves a response
********************************}
function GetResponse(APlayString: string; AChances, AMaxLen, AMaxVal, ATimeout: integer): string;
var
iLoops        : integer;
sRet          : string;
sConfirm      : string;
begin
// loop through number of times = AChances and attempt to retrieve a
// value from the caller.
for iLoops := 1 to AChances do
  begin
  // Play Prompt using supplied param
  sRet := Swift.ReadPlayString(APlayString, AMaxLen, ATimeout);
  // check response
  if (CheckResponse(sRet, AMaxVal, AMaxLen)) then
    begin
    sConfirm := Swift.ReadPlayString(PROMPT_VALUE + ' ' + sRet + '. ' + PROMPT_CONFIRM , 1, ATimeout);
    if (sConfirm = '1') then
      begin
      result := sRet;
      exit;
      end;
    end;
  // if AChances were not successful then play give up
  if (iLoops = AChances) then
    begin
    Swift.PlayString(PROMPT_ERROR_GIVEUP, false);
    sRet := '';
    exit;
    end;
  // otherwise, another pass is made through the loop because caller
  // did not enter correct answer.  Play error and allow to loop again.
  Swift.PlayString(PROMPT_ERROR, false);
  end;

end;

{********************************
Function ValidateUser
Validates a user extension number and pass code and populates a TUser structure
********************************}
function ValidateUser(APasscode, Xten: string; var AUser: TUser): TValidateReturn;
var
rowset: TDTRowSet;
sPass, sExten: string;
iActive: integer;
begin
result := false;

// Use SQLDB class to connect to database and verfy information.
with SQLDB do
   begin
   SetProp('sqltype', 'sql');
   SetProp('Connection', 'callutils');
   SetProp('sql', 'SELECT pass_code, user_id, user_first, user_last, is_admin, is_active, exten FROM ' +
     'sys_users WHERE exten = ' + Utility.QuotedStr(Xten) + ' AND pass_code = ' +
      Utility.QuotedStr(APasscode));

   if (not ConnectToDB) then
      begin
      result := vrConnectError;
      exit;
      end;

   if (not CreateRowSet('validate')) then
      begin
      AGI.Noop('CreateRowSet failed');
      result := vrNoRowset;
      exit;
      end;


   try // to ensure rowset is removed/freed

   // Rowsets (once successfully created)
   // are cached internally by the SQLDB object
   // and are thereafter referenced by name to manipulate
   // or remove from the cache.

   // get a reference to the new rowset created
   rowset := GetRowSet('validate');


   // check if value returned
   if (rowset.GetRecordCount > 0) then
      begin
      // get password and exten to match up
      sPass := rowset.AsString('pass_code');
      sExten := rowset.AsString('exten');

      // check extension provided
      if (sExten <> Xten) then
         begin
         result := vrBadExten;
         exit;
         end;

      // check passcode provided
      if (sPass <> APasscode) then
         begin
         result := vrBadPassword;
         exit;
         end;

      // is active?
      iActive := rowset.AsInteger('is_active');
      if (iActive <> 1) then
         begin
         result := vrNotActive;
         exit;
         end;

      // assume validated at this point
      AUser.UserID := rowset.AsString('user_id');
      AUser.UserFirst := rowset.AsString('user_first');
      AUser.UserLast := rowset.AsString('user_last');
      AUser.IsAdmin := (rowset.AsInteger('is_admin') = 1);
      AUser.Exten := sExten;
      // return validated response
      result := vrValidated;
      end
   else
      begin
      result := vrNotFound;
      exit;
      end;

   finally;
     RemoveRowset('validate'); // free rowset objects when finished
     end;

  end;
end ;