public override SubmissionStatus ServiceSubmit(string jobName, string fclInfo, Dictionary <string, string> driverSettings, Logger externalHandler, Stream xpsStream, int pageIndexStart, int pageIndexEnd, List <PageDimensions> pageDimensions)
        {
            AttachDebugger();

            var status = new SubmissionStatus();

            status.Result = false;

            try
            {
                string account  = GetPropertyResult("account", "");
                string username = GetPropertyResult("username", "");
                string password = GetPropertyResult("password", "");
                //string faxHeader = GetPropertyResult("faxHeader", "");
                string faxTag            = GetPropertyResult("faxTag", "");
                string callerId          = GetPropertyResult("callerId", "");
                string faxNumber         = GetPropertyResult("faxNumber", "");
                bool?  requireEncryption = GetPropertyResult <bool?>("requireEncryption", null);

                if (String.IsNullOrWhiteSpace(account))
                {
                    throw new Exception("Missing property: account");
                }
                if (String.IsNullOrWhiteSpace(username))
                {
                    throw new Exception("Missing property: username");
                }
                if (String.IsNullOrWhiteSpace(password))
                {
                    throw new Exception("Missing property: password");
                }
                //if (String.IsNullOrWhiteSpace(faxHeader))
                //{
                //    throw new Exception("Missing property: faxHeader");
                //}
                if (String.IsNullOrWhiteSpace(faxNumber))
                {
                    throw new Exception("Missing property: faxNumber");
                }
                if (requireEncryption == null)
                {
                    throw new Exception("Missing property: requireEncryption");
                }

                // Force OuptutImageType values. The user cannot change them for EtherFax.
                OutputImageTypeProperty outputImageType = new OutputImageTypeProperty("OutputImageType", "Output File Type")
                {
                    UserGenerated      = false,
                    DocxOutputAllowed  = false,
                    XpsOutputAllowed   = false,
                    PdfOutputAllowed   = false,
                    TiffOutputAllowed  = true,
                    RenderMode         = RenderModes.Raster_1,
                    RenderModesAllowed = new List <RenderModes>()
                    {
                        RenderModes.Raster_1
                    },

                    TiffCompression         = TiffCompressOption.Ccitt4,
                    TiffCompressionsAllowed = new List <TiffCompressOption>()
                    {
                        TiffCompressOption.Ccitt4
                    },

                    RenderPixelFormat         = PixelFormats.BlackWhite,
                    RenderPixelFormatsAllowed = new List <PixelFormats>()
                    {
                        PixelFormats.BlackWhite
                    }
                };

                /*
                 * https://tools.ietf.org/html/rfc2306
                 *
                 *  XResolution x Yresolution                  | ImageWidth
                 * --------------------------------------------|------------------
                 *  204x98, 204x196, 204x391, 200x100, 200x200 | 1728, 2048, 2432
                 *  300x300                                    | 2592, 3072, 3648
                 *  408x391, 400x400                           | 3456, 4096, 4864
                 * --------------------------------------------|------------------
                 *
                 * These are the fixed page widths in pixels.  The permissible values are dependent upon X and Y resolutions.
                 *
                 */

                int faxHorizontalResolution = 204;
                int faxVerticalResolution   = 196;

                outputImageType.HorizontalDpi = faxHorizontalResolution;
                outputImageType.VerticalDpi   = faxVerticalResolution;

                int faxPageWidth = 1728;  // 8.5" x 11" @ 204 x 196 dpi = 1734px x 2156px @ 99.6% => 1728px x 2148px (Desired fax width of 1728px @ 204 horizontal dpi)

                PointF pagePixels = pageDimensions[pageIndexStart].GetPixels(faxHorizontalResolution, faxVerticalResolution);

                float pageScaleRatio = faxPageWidth / pagePixels.X;
                int   faxPageHeight  = (int)(pageScaleRatio * pagePixels.Y);

                outputImageType.ImageDimensions = new System.Drawing.Point(faxPageWidth, faxPageHeight);

                DocumentRenderer renderingConverter = GetRenderer(outputImageType);
                if (renderingConverter != null)
                {
                    // Read the image to memory
                    byte[] fileBytes;


                    TempFileStream outputStream = null;
                    try
                    {
                        try
                        {
                            string tempFolder = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, @"Temp\");
                            Directory.CreateDirectory(tempFolder);
                            outputStream = new TempFileStream(tempFolder);
                        }
                        catch (Exception)
                        {
                            // Ignore - attempt another temp location (UAC may block UI test button from accessing the default Temp folder.)
                        }

                        if (outputStream == null)
                        {
                            string tempFolder = Path.Combine(Path.GetTempPath(), @"FS_UPD_v4\EtherFax\");
                            Directory.CreateDirectory(tempFolder);
                            outputStream = new TempFileStream(tempFolder);
                        }

                        renderingConverter.RenderXpsToOutput(xpsStream, outputStream, pageIndexStart, pageIndexEnd, externalHandler);
                        outputStream.Seek(0, SeekOrigin.Begin);

                        fileBytes = new byte[outputStream.Length];
                        outputStream.Read(fileBytes, 0, fileBytes.Length);
                    }
                    finally
                    {
                        if (outputStream != null)
                        {
                            outputStream.Dispose();
                            outputStream = null;
                        }
                    }


                    var offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);

                    status.Destination = "Fax: " + faxNumber;

                    var       client    = new SampleEtherFaxApi(account, username, password);
                    FaxStatus faxStatus = client.SendFax(faxNumber, faxTag, callerId, offset, fileBytes, ((pageIndexEnd - pageIndexStart) + 1), requireEncryption.Value);

                    if (faxStatus.FaxResult == FaxResult.InProgress)
                    {
                        status.Result            = true;
                        status.Message           = "Fax in progress.";
                        status.NextStatusRefresh = DateTime.Now.AddSeconds(30);
                        status.StatusCode        = 0;

                        var stateData = new UpdStatusState();
                        stateData.account          = account;
                        stateData.username         = username;
                        stateData.password         = Convert.ToBase64String(ProtectedData.Protect(Encoding.UTF8.GetBytes(password), _encryptionEntropy, DataProtectionScope.LocalMachine));
                        stateData.jobId            = faxStatus.JobId;
                        stateData.tagValue         = faxTag;
                        stateData.statusRetryCount = 0;

                        status.State = JsonConvert.SerializeObject(stateData);

                        status.LogDetails += "Submitted Fax with etherFAX ID: " + faxStatus.JobId + "\r\n";
                        status.LogDetails += "etherFAX Tag: " + faxTag + "\r\n";
                    }
                    else if (faxStatus.FaxResult == FaxResult.Success)
                    {
                        status.Result     = true;
                        status.Message    = "Your fax was delivered successfully.";
                        status.StatusCode = 100;
                        status.NotifyUser = true;

                        status.LogDetails  = "Your fax was delivered successfully!\r\n";
                        status.LogDetails += "Submitted Fax with etherFAX ID: " + faxStatus.JobId + "\r\n";
                        status.LogDetails += "etherFAX Tag: " + faxTag + "\r\n";
                    }
                    else if (faxStatus.FaxResult == FaxResult.Cancelled)
                    {
                        status.Result        = false;
                        status.Message       = "Your fax was cancelled.";
                        status.StatusCode    = 300;
                        status.SeverityLevel = StatusResults.SeverityLevels.Low;
                        status.NotifyUser    = true;

                        status.LogDetails  = "Fax cancelled:  " + faxStatus.ToString().Replace("_", " ") + "\r\n";
                        status.LogDetails += "Submitted Fax with etherFAX ID: " + faxStatus.JobId + "\r\n";
                        status.LogDetails += "etherFAX Tag: " + faxTag + "\r\n";
                    }
                    else // All errors
                    {
                        status.Result        = false;
                        status.Message       = "Your fax was not delivered. Reason: " + faxStatus.ToString().Replace("_", " ");
                        status.StatusCode    = 400 + (int)faxStatus.FaxResult;
                        status.SeverityLevel = StatusResults.SeverityLevels.High;
                        status.NotifyUser    = true;

                        status.LogDetails  = "Fax failed:  " + faxStatus.ToString().Replace("_", " ") + "\r\n";
                        status.LogDetails += "Submitted Fax with etherFAX ID: " + faxStatus.JobId + "\r\n";
                        status.LogDetails += "etherFAX Tag: " + faxTag + "\r\n";
                    }
                }
            }
            catch (WebException httpEx)
            {
                string webExDetails = "";

                using (var httpResponse = httpEx.Response as HttpWebResponse)
                {
                    if (httpResponse != null)
                    {
                        HttpStatusCode statusCode        = httpResponse.StatusCode;
                        string         statusDescription = httpResponse.StatusDescription;

                        string responseHeaders = httpResponse.Headers != null?httpResponse.Headers.ToString() : null;

                        using (Stream stream = httpResponse.GetResponseStream())
                        {
                            using (var sr = new StreamReader(stream))
                            {
                                string content = sr.ReadToEnd();
                                webExDetails = "Status: " + statusCode.ToString() + @"/" + statusDescription + "\r\n\r\n" + "Response: " + content;
                            }
                        }
                    }
                }

                status.Result     = false;
                status.Message    = "An error has occurred.";
                status.LogDetails = httpEx.Message + "\r\n\r\n" + webExDetails;
                status.NotifyUser = true;
                status.StatusCode = 11;
            }
            catch (Exception ex)
            {
                status.Result     = false;
                status.Message    = "An error has occurred.";
                status.LogDetails = ex.Message;
                status.NotifyUser = true;
                status.StatusCode = 12;
            }

            return(status);
        }
        public static new StatusResults RefreshStatus(SubmissionInfo submissionData, StatusResults previousStatus)
        {
            string additionalLogDetails = "";

            try
            {
                if (!string.IsNullOrWhiteSpace(previousStatus.State))
                {
                    var stateData = JsonConvert.DeserializeObject <UpdStatusState>(previousStatus.State);

                    additionalLogDetails += "Submitted Fax with etherFAX ID: " + stateData.jobId + "\r\n";
                    additionalLogDetails += "etherFAX Tag: " + stateData.tagValue + "\r\n";

                    string decryptedPassword = Encoding.UTF8.GetString(ProtectedData.Unprotect(Convert.FromBase64String(stateData.password), _encryptionEntropy, DataProtectionScope.LocalMachine));

                    var       client    = new SampleEtherFaxApi(stateData.account, stateData.username, decryptedPassword);
                    FaxStatus faxStatus = client.GetFaxStatus(stateData.jobId);

                    if (faxStatus.FaxResult == FaxResult.Success) // Success
                    {
                        return(new StatusResults()
                        {
                            Result = true,
                            StatusCode = 100,
                            Message = "Your fax was delivered successfully.",
                            NotifyUser = true,
                            LogDetails = "Your fax was delivered successfully!\r\n" + additionalLogDetails
                        });
                    }
                    else if (faxStatus.FaxResult == FaxResult.InProgress) // Incomplete - check status again
                    {
                        return(new StatusResults()
                        {
                            Result = false,
                            StatusCode = 200 + (int)faxStatus.State,
                            SeverityLevel = StatusResults.SeverityLevels.Low,
                            Message = "Fax in progress. " + faxStatus.State.ToString().Replace("_", " ") + "... " + faxStatus.PagesDelivered + " pages delivered.",
                            NextStatusRefresh = DateTime.Now.AddSeconds(30),
                            State = previousStatus.State,
                            LogDetails = "Fax in progress. " + faxStatus.State.ToString().Replace("_", " ") + "... " + faxStatus.PagesDelivered + " pages delivered.\r\n" + additionalLogDetails
                        });
                    }
                    else if (faxStatus.FaxResult == FaxResult.Cancelled) // Cancelled
                    {
                        return(new StatusResults()
                        {
                            Result = false,
                            StatusCode = 300,
                            SeverityLevel = StatusResults.SeverityLevels.Low,
                            Message = "Your fax was cancelled.",
                            LogDetails = "Fax cancelled: " + faxStatus.ToString().Replace("_", " ") + "\r\n" + additionalLogDetails,
                            NotifyUser = true
                        });
                    }
                    else // All errors
                    {
                        return(new StatusResults()
                        {
                            Result = false,
                            StatusCode = 400 + (int)faxStatus.FaxResult,
                            SeverityLevel = StatusResults.SeverityLevels.High,
                            Message = "Your fax was not delivered. Reason: " + faxStatus.ToString().Replace("_", " "),
                            LogDetails = "Fax failed: " + faxStatus.ToString().Replace("_", " ") + "\r\n" + additionalLogDetails,
                            NotifyUser = true
                        });
                    }
                }
                else
                {
                    return(new StatusResults()
                    {
                        Result = false,
                        StatusCode = 900,
                        SeverityLevel = StatusResults.SeverityLevels.Critical,
                        Message = "Cannot refresh the status. Reason: Missing state data.",
                        LogDetails = "Fax failed: Missing state data." + "\r\n" + additionalLogDetails,
                        NotifyUser = true
                    });
                }
            }
            catch (WebException httpEx)
            {
                string webExDetails = "";

                using (var httpResponse = httpEx.Response as HttpWebResponse)
                {
                    if (httpResponse != null)
                    {
                        HttpStatusCode statusCode        = httpResponse.StatusCode;
                        string         statusDescription = httpResponse.StatusDescription;

                        string responseHeaders = httpResponse.Headers != null?httpResponse.Headers.ToString() : null;

                        using (Stream stream = httpResponse.GetResponseStream())
                        {
                            using (var sr = new StreamReader(stream))
                            {
                                string content = sr.ReadToEnd();
                                webExDetails = "Status: " + statusCode.ToString() + @"/" + statusDescription + "\r\n\r\n" + "Response: " + content;
                            }
                        }
                    }
                }

                return(new StatusResults()
                {
                    Result = false,
                    StatusCode = 901,
                    SeverityLevel = StatusResults.SeverityLevels.Critical,
                    Message = "An error has occurred checking the status.",
                    NextStatusRefresh = DateTime.Now.AddSeconds(30),
                    LogDetails = httpEx.Message + "\r\n\r\n" + webExDetails + "\r\n" + additionalLogDetails,
                    NotifyUser = true,
                    State = previousStatus.State
                });
            }
            catch (Exception ex)
            {
                UpdStatusState stateData = null;
                try
                {
                    stateData = JsonConvert.DeserializeObject <UpdStatusState>(previousStatus.State);
                    stateData.statusRetryCount++;
                }
                catch (Exception stateEx)
                {
                    ex = new AggregateException(new List <Exception>()
                    {
                        ex, stateEx
                    });
                }

                var result = new StatusResults()
                {
                    Result            = false,
                    StatusCode        = 902,
                    SeverityLevel     = StatusResults.SeverityLevels.Critical,
                    Message           = "An error has occurred checking the status.",
                    NextStatusRefresh = DateTime.Now.AddSeconds(30),
                    LogDetails        = ex.Message + "\r\n" + additionalLogDetails,
                    NotifyUser        = true,
                    State             = previousStatus.State
                };
                if (stateData != null && stateData.statusRetryCount < MAX_REFRESH_ERRORS)
                {
                    result.NextStatusRefresh = DateTime.Now.AddSeconds(30);
                }
                return(result);
            }
        }
        protected override bool?UiSubmit(string jobName, string printerName, string fclInfo, Dictionary <string, string> driverSettings, Stream xpsStream)
        {
            AttachDebugger();

            bool validCredentials = false;

            string account = GetPropertyResult("account", "");

            // Read the credentials from the workflow
            string username = GetPropertyResult("username", "");
            string password = GetPropertyResult("password", "");

            var client1 = new SampleEtherFaxApi(account, username, password);

            if (client1.ValidateCredentials())
            {
                validCredentials = true;
            }
            else
            {
                // Prompt the user for credentials
                while (!validCredentials)
                {
                    var cred = new CredentialInputDialogWpf(null, false)
                    {
                        Topmost  = true,
                        Message  = "The workflow failed to authenticate to EtherFax. Please re-enter the credentials.",
                        Username = username,
                        UseWindowsCredentials = false,
                        NextText = "Ok"
                    };

                    if (cred.ShowDialog().Value)
                    {
                        var client2 = new SampleEtherFaxApi(account, cred.Username, cred.Password);
                        if (client2.ValidateCredentials())
                        {
                            validCredentials = true;
                            string updatedUsername = cred.Username;
                            string updatedPassword = cred.Password;

                            // Update the username and password values in the configured properties
                            StaticTextProperty usernameProperty = GetProperty <StaticTextProperty>("username");
                            if (usernameProperty != null)
                            {
                                usernameProperty.Value = updatedUsername;
                            }
                            StaticTextProperty passwordProperty = GetProperty <StaticTextProperty>("password");
                            if (passwordProperty != null)
                            {
                                passwordProperty.Value = updatedPassword;
                            }
                        }
                    }
                    else
                    {
                        break;
                    }
                }
            }

            if (validCredentials)
            {
                return(base.UiSubmit(jobName, printerName, fclInfo, driverSettings, xpsStream));
            }
            else
            {
                return(false);
            }
        }