public void SendAudio(AudioEventArgs args)
        {
            var chat = Chat as TLEncryptedChat;

            if (chat == null)
            {
                return;
            }

            if (string.IsNullOrEmpty(args.OggFileName))
            {
                return;
            }

            var dcId       = TLInt.Random();
            var id         = TLLong.Random();
            var accessHash = TLLong.Random();

            var oggFileName = String.Format("audio{0}_{1}.mp3", id, accessHash);
            var wavFileName = Path.GetFileNameWithoutExtension(oggFileName) + ".wav";

            long size = 0;

            using (var storage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                storage.MoveFile(args.OggFileName, oggFileName);
                using (var file = storage.OpenFile(oggFileName, FileMode.Open, FileAccess.Read))
                {
                    size = file.Length;
                }

                var wavStream = Wav.GetWavAsMemoryStream(args.PcmStream, 16000, 1, 16);
                using (var file = new IsolatedStorageFileStream(wavFileName, FileMode.OpenOrCreate, storage))
                {
                    wavStream.Seek(0, SeekOrigin.Begin);
                    wavStream.CopyTo(file);
                    file.Flush();
                }
            }

            var fileLocation = new TLEncryptedFile
            {
                Id             = id,
                AccessHash     = accessHash,
                DCId           = dcId,
                Size           = new TLInt((int)size),
                KeyFingerprint = new TLInt(0),
                FileName       = new TLString(Path.GetFileName(oggFileName))
            };

            var keyIV = GenerateKeyIV();
            TLDecryptedMessageMediaAudio decryptedMediaAudio;
            var encryptedChat17 = chat as TLEncryptedChat17;

            if (encryptedChat17 != null)
            {
                decryptedMediaAudio = new TLDecryptedMessageMediaAudio17
                {
                    Duration = new TLInt((int)args.Duration),
                    MimeType = new TLString("audio/ogg"),
                    Size     = new TLInt((int)size),
                    Key      = keyIV.Item1,
                    IV       = keyIV.Item2,

                    UserId = new TLInt(StateService.CurrentUserId),
                    File   = fileLocation,

                    UploadingProgress = 0.001
                };
            }
            else
            {
                decryptedMediaAudio = new TLDecryptedMessageMediaAudio
                {
                    Duration = new TLInt((int)args.Duration),
                    //MimeType = new TLString("audio/ogg"),
                    Size = new TLInt((int)size),
                    Key  = keyIV.Item1,
                    IV   = keyIV.Item2,

                    UserId = new TLInt(StateService.CurrentUserId),
                    File   = fileLocation,

                    UploadingProgress = 0.001
                };
            }

            var decryptedTuple = GetDecryptedMessageAndObject(TLString.Empty, decryptedMediaAudio, chat, true);

            BeginOnUIThread(() =>
            {
                Items.Insert(0, decryptedTuple.Item1);
                NotifyOfPropertyChange(() => DescriptionVisibility);
            });

            BeginOnThreadPool(() =>
                              CacheService.SyncDecryptedMessage(decryptedTuple.Item1, chat,
                                                                cachedMessage => SendAudioInternal(decryptedTuple.Item2)));
        }
        public void SendAudio(AudioEventArgs args)
        {
            var chat = Chat as TLEncryptedChat;

            if (chat == null)
            {
                return;
            }

            if (string.IsNullOrEmpty(args.OggFileName))
            {
                return;
            }

            var dcId       = TLInt.Random();
            var id         = TLLong.Random();
            var accessHash = TLLong.Random();

            var oggFileName = String.Format("audio{0}_{1}.mp3", id, accessHash);
            var wavFileName = Path.GetFileNameWithoutExtension(oggFileName) + ".wav";

            long size = 0;

            using (var storage = IsolatedStorageFile.GetUserStoreForApplication())
            {
                storage.MoveFile(args.OggFileName, oggFileName);
                using (var file = storage.OpenFile(oggFileName, FileMode.Open, FileAccess.Read))
                {
                    size = file.Length;
                }

                var wavStream = Wav.GetWavAsMemoryStream(args.PcmStream, 16000, 1, 16);
                using (var file = new IsolatedStorageFileStream(wavFileName, FileMode.OpenOrCreate, storage))
                {
                    wavStream.Seek(0, SeekOrigin.Begin);
                    wavStream.CopyTo(file);
                    file.Flush();
                }
            }

            var fileLocation = new TLEncryptedFile
            {
                Id             = id,
                AccessHash     = accessHash,
                DCId           = dcId,
                Size           = new TLInt((int)size),
                KeyFingerprint = new TLInt(0),
                FileName       = new TLString(Path.GetFileName(oggFileName))
            };

            var keyIV = GenerateKeyIV();
            TLDecryptedMessageMediaBase decryptedMediaAudio;
            var encryptedChat17 = chat as TLEncryptedChat17;

            if (encryptedChat17 != null)
            {
                if (encryptedChat17.Layer.Value >= Constants.MinSecretChatWithAudioAsDocumentsLayer)
                {
                    var opus          = new TelegramClient_Opus.WindowsPhoneRuntimeComponent();
                    var bytes         = opus.GetWaveform(ApplicationData.Current.LocalFolder.Path + "\\" + oggFileName);
                    var resultSamples = bytes.Length;
                    var bites2        = new BitArray(5 * bytes.Length);
                    var count         = 0;
                    for (var i = 0; i < bytes.Length; i++)
                    {
                        var result = bytes[i];
                        var bit1   = result >> 0 & 0x1;
                        var bit2   = result >> 1 & 0x1;
                        var bit3   = result >> 2 & 0x1;
                        var bit4   = result >> 3 & 0x1;
                        var bit5   = result >> 4 & 0x1;
                        bites2[count]     = Convert.ToBoolean(bit1);
                        bites2[count + 1] = Convert.ToBoolean(bit2);
                        bites2[count + 2] = Convert.ToBoolean(bit3);
                        bites2[count + 3] = Convert.ToBoolean(bit4);
                        bites2[count + 4] = Convert.ToBoolean(bit5);
                        count             = count + 5;
                    }

                    var bytesCount    = (resultSamples * 5) / 8 + (((resultSamples * 5) % 8) == 0 ? 0 : 1);
                    var waveformBytes = new byte[bytesCount];
                    bites2.CopyTo(waveformBytes, 0);
                    var waveform = waveformBytes != null?TLString.FromBigEndianData(waveformBytes) : TLString.Empty;

                    var audioAttribute = new TLDocumentAttributeAudio46
                    {
                        Flags    = new TLInt((int)DocumentAttributeAudioFlags.Voice),
                        Duration = new TLInt((int)args.Duration)
                    };

                    if (waveformBytes != null)
                    {
                        audioAttribute.Waveform = waveform;
                    }

                    var attributes = new TLVector <TLDocumentAttributeBase>
                    {
                        audioAttribute
                    };

                    decryptedMediaAudio = new TLDecryptedMessageMediaDocument45
                    {
                        Thumb       = TLString.Empty,
                        ThumbW      = new TLInt(0),
                        ThumbH      = new TLInt(0),
                        MimeType    = new TLString("audio/ogg"),
                        Size        = new TLInt((int)size),
                        Key         = keyIV.Item1,
                        IV          = keyIV.Item2,
                        Attributes  = attributes,
                        Caption     = TLString.Empty,
                        NotListened = true,

                        File = fileLocation,

                        UploadingProgress = 0.001
                    };
                }
                else
                {
                    decryptedMediaAudio = new TLDecryptedMessageMediaAudio17
                    {
                        Duration = new TLInt((int)args.Duration),
                        MimeType = new TLString("audio/ogg"),
                        Size     = new TLInt((int)size),
                        Key      = keyIV.Item1,
                        IV       = keyIV.Item2,

                        UserId = new TLInt(StateService.CurrentUserId),
                        File   = fileLocation,

                        UploadingProgress = 0.001
                    };
                }
            }
            else
            {
                decryptedMediaAudio = new TLDecryptedMessageMediaAudio
                {
                    Duration = new TLInt((int)args.Duration),
                    //MimeType = new TLString("audio/ogg"),
                    Size = new TLInt((int)size),
                    Key  = keyIV.Item1,
                    IV   = keyIV.Item2,

                    UserId = new TLInt(StateService.CurrentUserId),
                    File   = fileLocation,

                    UploadingProgress = 0.001
                };
            }

            var decryptedTuple = GetDecryptedMessageAndObject(TLString.Empty, decryptedMediaAudio, chat, true);

            //var message45 = decryptedTuple.Item1 as TLDecryptedMessage45;
            //if (message45 != null && message45.IsVoice())
            //{
            //    message45.NotListened = true;
            //}

            BeginOnUIThread(() =>
            {
                InsertSendingMessage(decryptedTuple.Item1);
                NotifyOfPropertyChange(() => DescriptionVisibility);
            });

            BeginOnThreadPool(() =>
                              CacheService.SyncDecryptedMessage(decryptedTuple.Item1, chat,
                                                                cachedMessage => SendAudioInternal(decryptedTuple.Item2)));
        }
        public void Handle(DownloadableItem item)
        {
            var decryptedMessage = item.Owner as TLDecryptedMessage;

            if (decryptedMessage != null)
            {
                var mediaExternalDocument = decryptedMessage.Media as TLDecryptedMessageMediaExternalDocument;
                if (mediaExternalDocument != null)
                {
                    decryptedMessage.NotifyOfPropertyChange(() => decryptedMessage.Self);
                }
            }

            var decryptedMedia = item.Owner as TLDecryptedMessageMediaBase;

            if (decryptedMedia != null)
            {
                decryptedMessage = Items.OfType <TLDecryptedMessage>().FirstOrDefault(x => x.Media == decryptedMedia);
                if (decryptedMessage != null)
                {
                    var mediaPhoto = decryptedMessage.Media as TLDecryptedMessageMediaPhoto;
                    if (mediaPhoto != null)
                    {
                        var fileName = item.IsoFileName;
                        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                        {
                            byte[] buffer;
                            using (var file = store.OpenFile(fileName, FileMode.Open, FileAccess.Read))
                            {
                                buffer = new byte[file.Length];
                                file.Read(buffer, 0, buffer.Length);
                            }
                            var fileLocation = decryptedMessage.Media.File as TLEncryptedFile;
                            if (fileLocation == null)
                            {
                                return;
                            }
                            var decryptedBuffer = Telegram.Api.Helpers.Utils.AesIge(buffer, mediaPhoto.Key.Data,
                                                                                    mediaPhoto.IV.Data, false);

                            var newFileName = String.Format("{0}_{1}_{2}.jpg",
                                                            fileLocation.Id,
                                                            fileLocation.DCId,
                                                            fileLocation.AccessHash);

                            using (var file = store.OpenFile(newFileName, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                file.Write(decryptedBuffer, 0, decryptedBuffer.Length);
                            }

                            store.DeleteFile(fileName);
                        }

                        decryptedMedia.NotifyOfPropertyChange("Self");
                    }

                    var mediaVideo = decryptedMessage.Media as TLDecryptedMessageMediaVideo;
                    if (mediaVideo != null)
                    {
                        mediaVideo.DownloadingProgress = 0.0;
                        var fileName = item.IsoFileName;
                        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                        {
                            byte[] buffer;
                            using (var file = store.OpenFile(fileName, FileMode.Open, FileAccess.Read))
                            {
                                buffer = new byte[file.Length];
                                file.Read(buffer, 0, buffer.Length);
                            }
                            var fileLocation = decryptedMessage.Media.File as TLEncryptedFile;
                            if (fileLocation == null)
                            {
                                return;
                            }
                            var decryptedBuffer = Telegram.Api.Helpers.Utils.AesIge(buffer, mediaVideo.Key.Data, mediaVideo.IV.Data, false);

                            var newFileName = String.Format("{0}_{1}_{2}.mp4",
                                                            fileLocation.Id,
                                                            fileLocation.DCId,
                                                            fileLocation.AccessHash);

                            using (var file = store.OpenFile(newFileName, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                file.Write(decryptedBuffer, 0, decryptedBuffer.Length);
                            }

                            store.DeleteFile(fileName);
                        }
                    }

                    var mediaAudio = decryptedMessage.Media as TLDecryptedMessageMediaAudio;
                    if (mediaAudio != null)
                    {
                        mediaAudio.DownloadingProgress = 0.0;

                        var fileLocation = decryptedMessage.Media.File as TLEncryptedFile;
                        if (fileLocation == null)
                        {
                            return;
                        }

                        var fileName          = item.IsoFileName;
                        var decryptedFileName = String.Format("audio{0}_{1}.mp3",
                                                              fileLocation.Id,
                                                              fileLocation.AccessHash);
                        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                        {
                            byte[] buffer;
                            using (var file = store.OpenFile(fileName, FileMode.Open, FileAccess.Read))
                            {
                                buffer = new byte[file.Length];
                                file.Read(buffer, 0, buffer.Length);
                            }
                            var decryptedBuffer = Telegram.Api.Helpers.Utils.AesIge(buffer, mediaAudio.Key.Data, mediaAudio.IV.Data, false);

                            using (var file = store.OpenFile(decryptedFileName, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                file.Write(decryptedBuffer, 0, decryptedBuffer.Length);
                            }

                            store.DeleteFile(fileName);
                        }

                        var wavFileName = Path.GetFileNameWithoutExtension(decryptedFileName) + ".wav";
#if WP8
                        var component = new WindowsPhoneRuntimeComponent();
                        var result    = component.InitPlayer(ApplicationData.Current.LocalFolder.Path + "\\" + decryptedFileName);
                        if (result == 1)
                        {
                            var buffer    = new byte[16 * 1024];
                            var args      = new int[3];
                            var pcmStream = new MemoryStream();
                            while (true)
                            {
                                component.FillBuffer(buffer, buffer.Length, args);
                                var count       = args[0];
                                var offset      = args[1];
                                var endOfStream = args[2] == 1;

                                pcmStream.Write(buffer, 0, count);
                                if (endOfStream)
                                {
                                    break;
                                }
                            }

                            var wavStream = Wav.GetWavAsMemoryStream(pcmStream, 48000, 1, 16);
                            using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                            {
                                using (var file = new IsolatedStorageFileStream(wavFileName, FileMode.OpenOrCreate, store))
                                {
                                    wavStream.Seek(0, SeekOrigin.Begin);
                                    wavStream.CopyTo(file);
                                    file.Flush();
                                }
                            }
                        }
#endif
                    }

                    var mediaDocument = decryptedMessage.Media as TLDecryptedMessageMediaDocument;
                    if (mediaDocument != null)
                    {
                        mediaDocument.DownloadingProgress = 0.0;
                        var fileName = item.IsoFileName;
                        using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                        {
                            byte[] buffer;
                            using (var file = store.OpenFile(fileName, FileMode.Open, FileAccess.Read))
                            {
                                buffer = new byte[file.Length];
                                file.Read(buffer, 0, buffer.Length);
                            }
                            var fileLocation = decryptedMessage.Media.File as TLEncryptedFile;
                            if (fileLocation == null)
                            {
                                return;
                            }
                            var decryptedBuffer = Telegram.Api.Helpers.Utils.AesIge(buffer, mediaDocument.Key.Data, mediaDocument.IV.Data, false);

                            var newFileName = String.Format("{0}_{1}_{2}.{3}",
                                                            fileLocation.Id,
                                                            fileLocation.DCId,
                                                            fileLocation.AccessHash,
                                                            fileLocation.FileExt);

                            using (var file = store.OpenFile(newFileName, FileMode.OpenOrCreate, FileAccess.Write))
                            {
                                file.Write(decryptedBuffer, 0, decryptedBuffer.Length);
                            }

                            store.DeleteFile(fileName);
                        }
                    }
                }
            }
        }
        public void Handle(DownloadableItem item)
        {
            Execute.BeginOnUIThread(() =>
            {
                var chatPhoto = item.Owner as TLChatPhoto;
                if (chatPhoto != null)
                {
                    var channel = With as TLChannel;
                    if (channel != null)
                    {
                        channel.NotifyOfPropertyChange(() => channel.Photo);
                        //channel.NotifyOfPropertyChange(() => channel.ChatPhoto);
                    }

                    var serviceMessages = Items.OfType <TLMessageService>();
                    foreach (var serviceMessage in serviceMessages)
                    {
                        var editPhoto = serviceMessage.Action as TLMessageActionChatEditPhoto;
                        if (editPhoto != null && editPhoto.Photo == chatPhoto)
                        {
                            editPhoto.NotifyOfPropertyChange(() => editPhoto.Photo);
                            break;
                        }
                    }
                }

                var message = item.Owner as TLMessage;
                if (message != null)
                {
                    var messages = Items.OfType <TLMessage>();
                    foreach (var m in messages)
                    {
                        var media = m.Media as TLMessageMediaVideo;
                        if (media != null && m == item.Owner)
                        {
                            m.Media.IsCanceled          = false;
                            m.Media.LastProgress        = 0.0;
                            m.Media.DownloadingProgress = 0.0;
                            m.NotifyOfPropertyChange(() => m.Self);
                            m.Media.IsoFileName = item.IsoFileName;
                            break;
                        }

                        var doc = m.Media as TLMessageMediaDocument;
                        if (doc != null && m == item.Owner)
                        {
                            m.Media.IsCanceled          = false;
                            m.Media.LastProgress        = 0.0;
                            m.Media.DownloadingProgress = 0.0;
                            m.Media.NotifyOfPropertyChange(() => m.Media.Self); // update download icon for documents
                            m.NotifyOfPropertyChange(() => m.Self);
                            m.Media.IsoFileName = item.IsoFileName;
                            break;
                        }

                        var audioMedia = m.Media as TLMessageMediaAudio;
                        if (audioMedia != null && m == item.Owner)
                        {
                            m.Media.IsCanceled          = false;
                            m.Media.LastProgress        = 0.0;
                            m.Media.DownloadingProgress = 0.0;
                            m.Media.IsoFileName         = item.IsoFileName;

                            var a = audioMedia.Audio as TLAudio;
                            if (a != null)
                            {
                                var fileName    = a.GetFileName();
                                var wavFileName = Path.GetFileNameWithoutExtension(fileName) + ".wav";
#if WP8
                                var component = new WindowsPhoneRuntimeComponent();
                                var result    = component.InitPlayer(ApplicationData.Current.LocalFolder.Path + "\\" + fileName);
                                if (result == 1)
                                {
                                    var buffer    = new byte[16 * 1024];
                                    var args      = new int[3];
                                    var pcmStream = new MemoryStream();
                                    while (true)
                                    {
                                        component.FillBuffer(buffer, buffer.Length, args);
                                        var count       = args[0];
                                        var offset      = args[1];
                                        var endOfStream = args[2] == 1;

                                        pcmStream.Write(buffer, 0, count);
                                        if (endOfStream)
                                        {
                                            break;
                                        }
                                    }

                                    var wavStream = Wav.GetWavAsMemoryStream(pcmStream, 48000, 1, 16);
                                    using (var store = IsolatedStorageFile.GetUserStoreForApplication())
                                    {
                                        using (var file = new IsolatedStorageFileStream(wavFileName, FileMode.OpenOrCreate, store))
                                        {
                                            wavStream.Seek(0, SeekOrigin.Begin);
                                            wavStream.CopyTo(file);
                                            file.Flush();
                                        }
                                    }
                                }
#endif
                            }

                            break;
                        }
                    }
                    return;
                }

                var photo = item.Owner as TLPhoto;
                if (photo != null)
                {
                    var isUpdated = false;
                    var messages  = Items.OfType <TLMessage>();
                    foreach (var m in messages)
                    {
                        var mediaPhoto = m.Media as TLMessageMediaPhoto;
                        if (mediaPhoto != null && mediaPhoto.Photo == photo)
                        {
                            mediaPhoto.NotifyOfPropertyChange(() => mediaPhoto.Photo);
                            mediaPhoto.NotifyOfPropertyChange(() => mediaPhoto.Self);
                            isUpdated = true;
                            break;
                        }

                        var mediaWebPage = m.Media as TLMessageMediaWebPage;
                        if (mediaWebPage != null && mediaWebPage.Photo == photo)
                        {
                            mediaWebPage.NotifyOfPropertyChange(() => mediaWebPage.Photo);
                            mediaWebPage.NotifyOfPropertyChange(() => mediaWebPage.Self);
                            isUpdated = false;
                            break;
                        }
                    }

                    if (isUpdated)
                    {
                        return;
                    }

                    var serviceMessages = Items.OfType <TLMessageService>();
                    foreach (var serviceMessage in serviceMessages)
                    {
                        var editPhoto = serviceMessage.Action as TLMessageActionChatEditPhoto;
                        if (editPhoto != null && editPhoto.Photo == photo)
                        {
                            editPhoto.NotifyOfPropertyChange(() => editPhoto.Photo);
                            isUpdated = true;
                            break;
                        }
                    }
                }

                var document = item.Owner as TLDocument;
                if (document != null)
                {
                    var messages = Items.OfType <TLMessage>();
                    foreach (var m in messages)
                    {
                        var media = m.Media as TLMessageMediaDocument;
                        if (media != null && TLDocumentBase.DocumentEquals(media.Document, document))
                        {
                            media.NotifyOfPropertyChange(() => media.Document);
                            break;
                        }
                    }
                }

                var video = item.Owner as TLVideo;
                if (video != null)
                {
                    var messages = Items.OfType <TLMessage>();
                    foreach (var m in messages)
                    {
                        var media = m.Media as TLMessageMediaVideo;
                        if (media != null && media.Video == video)
                        {
                            media.NotifyOfPropertyChange(() => media.Video);
                            break;
                        }
                    }
                }

                var audio = item.Owner as TLAudio;
                if (audio != null)
                {
                    var messages = Items.OfType <TLMessage>();
                    foreach (var m in messages)
                    {
                        var media = m.Media as TLMessageMediaAudio;
                        if (media != null && media.Audio == audio)
                        {
                            media.NotifyOfPropertyChange(() => media.Audio);
                            break;
                        }
                    }
                }

                var webPage = item.Owner as TLWebPage;
                if (webPage != null)
                {
                    var messages = Items.OfType <TLMessage>();
                    foreach (var m in messages)
                    {
                        var media = m.Media as TLMessageMediaWebPage;
                        if (media != null && media.WebPage == webPage)
                        {
                            media.NotifyOfPropertyChange(() => media.Photo);
                            media.NotifyOfPropertyChange(() => media.Self);
                            break;
                        }
                    }
                }
            });
        }