private void PreloadResultHistory(TLMessageBase message)
        {
            var maxId  = message.Id;
            var offset = new TLInt(-6);
            var limit  = new TLInt(14);

            IList <TLMessageBase> resultHistory;

            if (_resultHistoryCache.TryGetValue(maxId.Value, out resultHistory))
            {
                return;
            }

            IsWorking = true;
            MTProtoService.GetHistoryAsync("PreloadResultHistory", Peer, TLUtils.InputPeerToPeer(Peer, StateService.CurrentUserId), false, offset, maxId, limit,
                                           result => BeginOnUIThread(() =>
            {
                IsWorking = false;

                ProcessRepliesAndAudio(result.Messages);

                _resultHistoryCache[maxId.Value] = result.Messages;
            }),
                                           error => BeginOnUIThread(() =>
            {
                IsWorking = false;
                Execute.ShowDebugMessage("messages.getHistory error " + error);
            }));
        }
        private void SearchAsync(TLString text, DateTime?date, TLUserBase from, TLInt maxId, TLInt limit)
        {
            var maxDate = date != null
                ? TLUtils.DateToUniversalTimeTLInt(MTProtoService.ClientTicksDelta, date.Value.AddDays(1).AddSeconds(-1))
                : null;

            if (TLString.IsNullOrEmpty(text) && date.HasValue)
            {
                IsWorking = true;
                MTProtoService.GetHistoryAsync(
                    Stopwatch.StartNew(),
                    Peer,
                    TLUtils.InputPeerToPeer(Peer, StateService.CurrentUserId),
                    false, maxDate ?? new TLInt(0),
                    new TLInt(0),
                    maxId,
                    new TLInt(1),
                    result => BeginOnUIThread(() =>
                {
                    var messagesSlice = result as TLMessagesSlice;
                    if (messagesSlice != null)
                    {
                        messagesSlice.Count = new TLInt(messagesSlice.Messages.Count);
                    }

                    IsWorking = false;

                    ProcessMessages(result.Messages);

                    var key = GetKey(text.ToString(), date, from);

                    TLMessagesBase cachedResult;
                    if (_searchResults.TryGetValue(key, out cachedResult))
                    {
                        var lastId = cachedResult.Messages.Last().Id;
                        if (lastId.Value == maxId.Value)
                        {
                            var cachedUsersIndex = new Dictionary <int, int>();
                            foreach (var cachedUser in cachedResult.Users)
                            {
                                cachedUsersIndex[cachedUser.Index] = cachedUser.Index;
                            }
                            foreach (var user in result.Users)
                            {
                                if (!cachedUsersIndex.ContainsKey(user.Index))
                                {
                                    cachedResult.Users.Add(user);
                                }
                            }
                            var cachedChatsIndex = new Dictionary <int, int>();
                            foreach (var cachedChat in cachedResult.Chats)
                            {
                                cachedChatsIndex[cachedChat.Index] = cachedChat.Index;
                            }
                            foreach (var chat in result.Chats)
                            {
                                if (!cachedChatsIndex.ContainsKey(chat.Index))
                                {
                                    cachedResult.Chats.Add(chat);
                                }
                            }
                            foreach (var message in result.Messages)
                            {
                                cachedResult.Messages.Add(message);
                            }

                            SearchMessages.ResultLoaded(_currentResultIndex, cachedResult.Messages.Count);
                        }
                    }
                    else
                    {
                        _searchResults[key] = result;
                        var currentKey      = GetKey(SearchMessages.Text, SearchMessages.Date, SearchMessages.From);
                        if (string.Equals(key, currentKey, StringComparison.Ordinal))
                        {
                            ContinueSearch(result);
                        }
                    }
                }),
                    error => BeginOnUIThread(() =>
                {
                    IsWorking = false;
                    Execute.ShowDebugMessage("messages.search error " + error);
                }));
            }
            else
            {
                IsWorking = true;
                MTProtoService.SearchAsync(
                    Peer,
                    text,
                    from == null ? null : from.ToInputUser(),
                    new TLInputMessagesFilterEmpty(),
                    new TLInt(0),
                    maxDate ?? new TLInt(0),
                    new TLInt(0),
                    maxId,
                    limit,
                    new TLInt(0),
                    result => BeginOnUIThread(() =>
                {
                    IsWorking = false;

                    ProcessMessages(result.Messages);

                    var key = GetKey(text.ToString(), date, from);

                    TLMessagesBase cachedResult;
                    if (_searchResults.TryGetValue(key, out cachedResult))
                    {
                        var lastId = cachedResult.Messages.Last().Id;
                        if (lastId.Value == maxId.Value)
                        {
                            var cachedUsersIndex = new Dictionary <int, int>();
                            foreach (var cachedUser in cachedResult.Users)
                            {
                                cachedUsersIndex[cachedUser.Index] = cachedUser.Index;
                            }
                            foreach (var user in result.Users)
                            {
                                if (!cachedUsersIndex.ContainsKey(user.Index))
                                {
                                    cachedResult.Users.Add(user);
                                }
                            }
                            var cachedChatsIndex = new Dictionary <int, int>();
                            foreach (var cachedChat in cachedResult.Chats)
                            {
                                cachedChatsIndex[cachedChat.Index] = cachedChat.Index;
                            }
                            foreach (var chat in result.Chats)
                            {
                                if (!cachedChatsIndex.ContainsKey(chat.Index))
                                {
                                    cachedResult.Chats.Add(chat);
                                }
                            }
                            foreach (var message in result.Messages)
                            {
                                cachedResult.Messages.Add(message);
                            }

                            SearchMessages.ResultLoaded(_currentResultIndex, cachedResult.Messages.Count);
                        }
                    }
                    else
                    {
                        _searchResults[key] = result;
                        var currentKey      = GetKey(SearchMessages.Text, SearchMessages.Date, SearchMessages.From);
                        if (string.Equals(key, currentKey, StringComparison.Ordinal))
                        {
                            ContinueSearch(result);
                        }
                    }
                }),
                    error => BeginOnUIThread(() =>
                {
                    IsWorking = false;
                    Execute.ShowDebugMessage("messages.search error " + error);
                }));
            }
        }
        public void OpenReply(TLMessageBase message)
        {
            if (message == null)
            {
                return;
            }

            var reply = message.Reply as TLMessageCommon;

            if (reply == null)
            {
                return;
            }
            if (reply.Index == 0)
            {
                return;
            }

            // migrated reply
            var channel = With as TLChannel;

            if (channel != null)
            {
                var replyPeerChat = reply.ToId as TLPeerChat;
                if (replyPeerChat != null)
                {
                    for (var i = 0; i < Items.Count; i++)
                    {
                        var item = Items[i] as TLMessageCommon;
                        if (item != null)
                        {
                            var peerChat = item.ToId as TLPeerChat;
                            if (peerChat != null)
                            {
                                if (Items[i].Index == reply.Index)
                                {
                                    RaiseScrollTo(new ScrollToEventArgs(Items[i]));

                                    //waiting ScrollTo to complete
                                    BeginOnUIThread(TimeSpan.FromSeconds(0.1), () =>
                                    {
                                        HighlightMessage(Items[i]);

                                        _previousScrollPosition  = message;
                                        ScrollToBottomVisibility = Visibility.Visible;
                                    });

                                    return;
                                }
                            }
                        }
                    }

                    return;
                }
            }

            for (var i = 0; i < Items.Count; i++)
            {
                if (Items[i].Index == reply.Index)
                {
                    RaiseScrollTo(new ScrollToEventArgs(Items[i]));

                    //waiting ScrollTo to complete
                    BeginOnUIThread(TimeSpan.FromSeconds(0.1), () =>
                    {
                        HighlightMessage(Items[i]);

                        _previousScrollPosition  = message;
                        ScrollToBottomVisibility = Visibility.Visible;
                    });
                    return;
                }
            }

            return;

            // load separated slice with reply
            Items.Clear();
            Items.Add(message.Reply);
            ScrollToBottomVisibility = Visibility.Visible;
            _isFirstSliceLoaded      = false;

            var key = string.Format("{0}", message.Reply.Index);
            IList <TLMessageBase> cachedMessage;

            if (_getHistoryCache.TryGetValue(key, out cachedMessage))
            {
                OpenReplyInternal(message.Reply, cachedMessage);
            }
            else
            {
                IsWorking = true;
                MTProtoService.GetHistoryAsync(
                    "OpenReply",
                    Peer,
                    TLUtils.InputPeerToPeer(Peer, StateService.CurrentUserId),
                    false,
                    new TLInt(-15),
                    new TLInt(message.Reply.Index),
                    new TLInt(30),
                    result =>
                {
                    ProcessRepliesAndAudio(result.Messages);
                    _getHistoryCache[key] = result.Messages;

                    BeginOnUIThread(() =>
                    {
                        OpenReplyInternal(message.Reply, result.Messages);
                        IsWorking = false;
                    });
                },
                    error =>
                {
                    Execute.ShowDebugMessage("messages.getHistory error " + error);
                    IsWorking = false;
                });
            }
        }