protected virtual void Dispose(bool disposing)
        {
            if (!this.disposedValue)
            {
                if (disposing)
                {
                    if (this._CancellationTokenSource != null)
                    {
                        try
                        {
                            this._CancellationTokenSource.Cancel(false);
                        }
                        catch (Exception exp)
                        {
                            if (_Logger.IsWarnEnabled)
                            {
                                _Logger.Warn(exp, "Error while canceling the current requests");
                            }
                        }

                        this._CancellationTokenSource = null;
                    }

                    if (this._CurrentEditor != null)
                    {
                        this._CurrentEditor.Dispose();
                        this._CurrentEditor = null;
                    }
                }

                this.disposedValue = true;
            }
        }
        public async Task LaunchAsync(CancellationTokenSource cancellationTokenSource = null)
        {
            if (this._CurrentEditor != null)
            {
                if (_Logger.IsWarnEnabled)
                {
                    _Logger.Warn("The current editor is not null");
                }

                return;
            }

            this._CancellationTokenSource = cancellationTokenSource;
            try
            {
                var messageInfo = await this._SessionData.GetMessageInfoAsync(cancellationTokenSource);

                if (messageInfo == null)
                {
                    if (_Logger.IsErrorEnabled)
                    {
                        _Logger.Error("Error while getting message info");
                    }
                    return;
                }

                var isReadOnly = !messageInfo.GetJsonValue <bool>("access.canChangeBody");

                bool needsHeader = !StringComparer.OrdinalIgnoreCase.Equals(messageInfo.GetJsonValue <string>("class.ref"), @"Varedeh");


                var content = await this._SessionData.GetMessageContentAsync(needsHeader && this.InsertHeader, isReadOnly&& this.InsertSigns, isReadOnly&& this.InsertSignImage, isReadOnly&& this.InsertCopyText, isReadOnly&& this.InsertRemarks, cancellationTokenSource);

                if (_Logger.IsDebugEnabled)
                {
                    _Logger.Debug("Message content loaded");
                }

                var messageDisplayName = messageInfo.GetJsonValue <string>("displayName") ?? Guid.NewGuid().ToString();

                if (_Logger.IsDebugEnabled)
                {
                    _Logger.Debug("Message display name is {0}", messageDisplayName);
                }

                var msgInfo = new MessageInfo(this._SessionData, messageDisplayName);

                lock (_MessagesSyncObj)
                {
                    _Messages.Add(msgInfo);
                }


                try
                {
                    if (_Logger.IsDebugEnabled)
                    {
                        _Logger.Debug("Creating temp file");
                    }

                    var tempFile = GetTempFileName(messageDisplayName);

                    if (_Logger.IsDebugEnabled)
                    {
                        _Logger.Debug("The temp file is {0}", tempFile);
                    }

                    if (cancellationTokenSource == null)
                    {
                        await TaskEx.Run(() => File.WriteAllBytes(tempFile, content));
                    }
                    else
                    {
                        await TaskEx.Run(() => File.WriteAllBytes(tempFile, content), cancellationTokenSource.Token);
                    }

                    if (_Logger.IsInfoEnabled)
                    {
                        _Logger.Info("The temp file is {0}", tempFile);
                    }

                    try
                    {
                        var fi = new FileInfo(tempFile);

                        Debug.Assert(fi.Exists, "The temp file not found", "File not found: {0}", tempFile);

                        //fi.IsReadOnly = isReadOnly;
                        fi.CreationTime  = messageInfo.GetJsonValue <DateTime?>("createdAt") ?? DateTime.Now;
                        fi.LastWriteTime = messageInfo.GetJsonValue <DateTime?>("changedAt") ?? DateTime.Now;
                    }
                    catch (Exception exp)
                    {
                        if (_Logger.IsWarnEnabled)
                        {
                            _Logger.Warn(exp, "Error while setting temp file info");
                        }
                    }

                    if (isReadOnly)
                    {
                        _Logger.Info("The message is read only");
                    }

                    var canPrint = messageInfo.GetJsonValue <bool>("access.canPrint");

                    using (var editor = new WordEditor(tempFile, (isReadOnly ? WordEditorPermissions.None : WordEditorPermissions.Change) | (canPrint ? WordEditorPermissions.Print : WordEditorPermissions.None), msgInfo))
                    {
                        this._CurrentEditor = editor;

                        await TaskEx.Delay(110);

                        try
                        {
                            Func <Task> launch = async() => await editor.LaunchAsync(cancellationTokenSource).ConfigureAwait(true);

                            await(Task) System.Windows.Application.Current.Dispatcher.Invoke(launch);

                            if (editor.IsSaved)
                            {
                                if (_Logger.IsDebugEnabled)
                                {
                                    _Logger.Debug("Editor closed with save");
                                }

                                if (File.Exists(tempFile))
                                {
                                    var body = await Utility.ReadAllBytesAsync(tempFile, cancellationTokenSource);

                                    if (body.Length == 0)
                                    {
                                        if (_Logger.IsWarnEnabled)
                                        {
                                            _Logger.Warn("The current editing file is empty");
                                        }
                                        return;
                                    }

                                    if (_Logger.IsDebugEnabled)
                                    {
                                        _Logger.Debug("Uploading the message body");
                                    }

                                    var result = await this._SessionData.SetBodyAsync(body, cancellationTokenSource : cancellationTokenSource);

                                    if (result != null && !result.IsSuccess)
                                    {
                                        if (_Logger.IsErrorEnabled)
                                        {
                                            _Logger.Error("Error while uploading the message body to the server: {0}", result.Message);
                                        }
                                    }
                                }

                                return;
                            }
                            else
                            {
                                if (_Logger.IsDebugEnabled)
                                {
                                    _Logger.Debug("Editor closed with no save");
                                }

                                return;
                            }
                        }
                        catch (Exception exp)
                        {
                            if (_Logger.IsErrorEnabled)
                            {
                                _Logger.Error(exp, "Launching error in WordEditor");
                            }

                            throw;
                        }
                        finally
                        {
                            this._CurrentEditor = null;
                        }
                    }
                }
                catch (Exception exp)
                {
                    if (_Logger.IsErrorEnabled)
                    {
                        _Logger.Error(exp, "Launching error in creation");
                    }

                    throw;
                }
                finally
                {
                    lock (_MessagesSyncObj)
                    {
                        _Messages.Remove(msgInfo);
                    }
                }
            }
            catch (Exception exp)
            {
                if (_Logger.IsErrorEnabled)
                {
                    _Logger.Error(exp, "Launching error");
                }

                throw;
            }
            finally
            {
                this._CancellationTokenSource = null;
            }
        }
        public async Task PrintAsync(bool withPreview, CancellationTokenSource cancellationTokenSource = null)
        {
            if (this._CurrentEditor != null)
            {
                return;
            }

            this._CancellationTokenSource = cancellationTokenSource;
            try
            {
                var messageInfo = await this._SessionData.GetMessageInfoAsync(cancellationTokenSource);

                if (messageInfo == null)
                {
                    return;
                }

                //var hasPrintPermission = messageInfo.GetJsonValue<bool>("access.canPrint");
                //if (!hasPrintPermission)
                //    throw new SecurityException("Print permission denied");

                bool insertHeader;
                if (this.InsertHeader)
                {
                    if (StringComparer.OrdinalIgnoreCase.Equals(messageInfo.GetJsonValue <string>("class.ref"), @"Varedeh"))
                    {
                        insertHeader = false;
                    }
                    else
                    {
                        insertHeader = true;
                    }
                }
                else
                {
                    insertHeader = false;
                }

                var content = await this._SessionData.GetMessageContentAsync(insertHeader, this.InsertSigns, this.InsertSignImage, this.InsertCopyText, this.InsertRemarks, cancellationTokenSource);

                if (content == null)
                {
                    return;
                }

                var messageDisplayName = messageInfo.GetJsonValue <string>("displayName");

                var tempFile = GetTempFileName(messageDisplayName);

                if (cancellationTokenSource == null)
                {
                    await TaskEx.Run(() => File.WriteAllBytes(tempFile, content));
                }
                else
                {
                    await TaskEx.Run(() => File.WriteAllBytes(tempFile, content), cancellationTokenSource.Token);
                }

                try
                {
                    var fi = new FileInfo(tempFile);

                    Debug.Assert(fi.Exists, "The temp file not found", "File not found: {0}", tempFile);

                    //fi.IsReadOnly = true;
                    fi.CreationTime  = messageInfo.GetJsonValue <DateTime?>("createdAt") ?? DateTime.Now;
                    fi.LastWriteTime = messageInfo.GetJsonValue <DateTime?>("changedAt") ?? DateTime.Now;
                }
                catch (Exception exp)
                {
                    if (_Logger.IsWarnEnabled)
                    {
                        _Logger.Warn(exp, "Error while setting temp file info");
                    }
                }

                using (var editor = new WordEditor(tempFile, WordEditorPermissions.Print, new MessageInfo(this._SessionData, messageDisplayName)))
                {
                    this._CurrentEditor = editor;

                    try
                    {
                        await editor.PrintAsync(withPreview, cancellationTokenSource);
                    }
                    finally
                    {
                        this._CurrentEditor = null;
                    }
                }
            }
            finally
            {
                this._CancellationTokenSource = null;
            }
        }