using Microsoft.AspNetCore.Components;
using Blog3000.Shared;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using System.Net.Http;
using Microsoft.JSInterop;
namespace Blog3000.Client.Shared
{
public partial class PostFinder : IDisposable
{
public class State
{
public int StartIdx;
public string Search;
}
///
/// Could be use with dict/startIdKey for use on different pages
///
private static State CurrentState = new State();
[Inject]
private BlogDb BlogDb { get; set; }
[Inject]
private NetworkStatus NetworkStatus { get; set; }
[Inject]
private HttpClient Http { get; set; }
[Inject]
private IJSRuntime JSRuntime { get; set; }
private string errorMsg { get; set; }
private string dispMode { get; set; }
private string PageInfo
{
get
{
var res = $"{StartIdx + 1}-{StartIdx + 0 + pageSize} ";
if (totalPostsFound != null)
{
if (totalPostsFound == 1)
{
res += $"(of 1)";
}
else if (totalPostsFound > 1)
{
res += $"(of {totalPostsFound})";
}
}
return res;
}
}
private ElementReference ScrollAnchorElement;
private string SearchText { get; set; }
private int StartIdx
{
get
{
return startIdx;
}
set
{
startIdx = value;
OnStartIdxChanged();
}
}
private int startIdx = 0;
private int pageSize = 6;
private int pageMaxSize = 6;
private int? totalPostsFound = null;
private List selectedPosts = new List();
public void Dispose()
{
BlogDb.BlogPostsChanged -= BlogDb_BlogPostsChanged;
}
public async void StartSearch(string searchString)
{
System.Diagnostics.Debug.WriteLine($"Got searchstring {searchString}");
SearchText = searchString;
// await SelectPosts();
// StateHasChanged();
UpdateSearch();
}
protected override async Task OnInitializedAsync()
{
StartIdx = CurrentState.StartIdx;
SearchText = CurrentState.Search;
BlogDb.BlogPostsChanged += BlogDb_BlogPostsChanged;
await SelectPosts();
}
private async void BlogDb_BlogPostsChanged(object sender, EventArgs e)
{
await SelectPosts();
this.StateHasChanged();
}
private void GotoFirst()
{
System.Diagnostics.Debug.WriteLine("Goto first");
StartIdx = 0;
}
private void GotoNext()
{
StartIdx += pageMaxSize;
}
private void GotoPrev()
{
StartIdx -= pageMaxSize;
}
private async void ClearSearch()
{
errorMsg = null;
SearchText = "";
startIdx = 0;
totalPostsFound = null;
await SelectPosts();
StateHasChanged();
CurrentState.StartIdx = StartIdx;
CurrentState.Search = "";
}
private async void UpdateSearch()
{
errorMsg = null;
startIdx = 0;
totalPostsFound = null;
await SelectPosts();
StateHasChanged();
CurrentState.StartIdx = StartIdx;
CurrentState.Search = SearchText;
_ = JSRuntime.InvokeVoidAsync("scrollElmIntoView", ScrollAnchorElement);
}
private async void OnStartIdxChanged()
{
if (startIdx < 0) startIdx = 0;
await SelectPosts();
if (selectedPosts.Count == 0 && startIdx > 0)
{
// Too far, go back one page
StartIdx -= pageMaxSize;
await SelectPosts();
// Bad input? instruct DB to find last page
if (selectedPosts.Count == 0 && startIdx > 0)
{
await SelectPosts(true);
}
}
StateHasChanged();
CurrentState.StartIdx = StartIdx;
}
private async Task SelectPosts(bool findLastPage = false)
{
bool fulltextIsLocallyAvail = await BlogDb.IsEagerLoading();
bool isOnline = NetworkStatus.IsOnline;
var bps = new BlogPostSearch(() => BlogDb.GetCachedPostsAsync(), () => BlogDb.GetHeadersAsync(), SearchText);
if (!bps.IsNonEmptyTerm)
{
dispMode = "Last posts";
}
else
{
// Brutal fulltext search.. Should be good for the first 100 articles or so...
dispMode = "Search";
}
if (!bps.IsNonEmptyTerm)
{
var res = await bps.ExecAsync(startIdx, pageMaxSize, findLastPage);
pageSize = res.Count;
totalPostsFound = await BlogDb.GetHeadersAsync()
.Where(a => "PUBLIC".Equals(a.Access))
.Where(p => (p.StickyMenuPos ?? -1) < 0)
.CountAsync();
selectedPosts = res;
}
else
{
bool needsFullText = bps.RequiresFullText;
if (!fulltextIsLocallyAvail && needsFullText)
{
if (!isOnline)
{
errorMsg = "Offline, search not possible";
return;
}
else
{
try
{
var url = $"/BlogPosts/search?searchTerm={System.Net.WebUtility.UrlEncode(SearchText)}&startIdx={startIdx}&pageMaxSize={pageMaxSize}&findLastPage={findLastPage}";
var ids = await Http.GetJsonAsync>(url);
var res = new List();
foreach (var id in ids)
{
var bp = await BlogDb.GetHeaderAsync(id);
if (bp != null)
{
res.Add(bp);
}
await Task.Yield();
}
pageSize = res.Count;
selectedPosts = res;
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine($"Exception during search: {ex}");
errorMsg = $"Error during search: {ex.Message}";
}
}
}
else
{
var efetch = BlogDb.GetCachedPostsAsync();
var res = await bps.ExecAsync(startIdx, pageMaxSize, findLastPage);
pageSize = res.Count;
selectedPosts = res;
}
}
}
}
}