using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Text.RegularExpressions;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.ModelBinding;
using Microsoft.AspNetCore.Mvc.ModelBinding.Validation;
using Microsoft.AspNetCore.Mvc.ViewFeatures;
using Microsoft.AspNetCore.WebUtilities;
using Microsoft.Extensions.Primitives;
namespace BTCPayServer.Models
{
public abstract class BasePagingViewModel
{
public const int CountDefault = 50;
public int Skip { get; set; } = 0;
public int Count { get; set; } = CountDefault;
public int? Total { get; set; }
///
/// SearchTerm is the part of the SearchString that isn't shown explicitly
/// in the search text input.
///
[DisplayFormat(ConvertEmptyStringToNull = false)]
public string SearchTerm { get; set; }
[BindingBehavior(BindingBehavior.Never)]
[ValidateNever]
public SearchString Search { get; set; }
///
/// SearchText is the part of the SearchString that is shown explicitly in the search text input.
///
public string SearchText { get; set; }
public string FilterCommand { get; set; }
public SearchString GetSearch()
{
var search = SearchString.Combine([SearchTerm, SearchText]);
search.RemoveDups("daterange");
if (FilterCommand is not null)
RunFilterCommand(search);
AddUIFilters(search);
SearchTerm = search.ToString(SearchStringFormat.OnlyUIFilters);
SearchText = search.ToString(SearchStringFormat.ExceptUIFilters);
Search = search;
return search;
}
protected virtual void AddUIFilters(SearchString search)
{
}
protected virtual void RunFilterCommand(SearchString search)
{
if (Regex.Match(FilterCommand, @"^(set|set-multi):") is { Success: true } match)
{
var kv = FilterCommand.Substring(match.Value.Length).Split('=', 2);
if (kv.Length == 2)
{
search.SetFilter(kv[0], kv[1], true, "set-multi:" == match.Value);
}
}
if (FilterCommand.StartsWith("set-timezone:"))
{
var tz = FilterCommand.Substring("set-timezone:".Length);
if (TimeZones.TryGet(tz) is { } tzo)
search.SetFilter("timezone", tzo.Id);
}
if (FilterCommand.StartsWith("unset:"))
{
var k = FilterCommand.Substring("unset:".Length);
search.SetFilter(k);
}
if (FilterCommand is "reset")
{
var tz = search.GetFilterString("timezone");
search.Filters.Clear();
if (tz != null)
search.SetFilter("timezone", tz);
search.TextSearch = "";
return;
}
if (FilterCommand is "alltime")
{
search.Filters.Remove("daterange");
search.Filters.Remove("startdate");
search.Filters.Remove("enddate");
}
if (FilterCommand.StartsWith("set-daterange:"))
{
var dateRange = FilterCommand.Substring("set-daterange:".Length);
if (SearchString.IsValidDateRange(dateRange))
search.SetDateRange(dateRange, true);
}
}
public IActionResult Redirect(HttpRequest request)
{
var query = QueryHelpers.ParseQuery(request.QueryString.Value);
var newQuery = query.ToDictionary(
x => x.Key,
x => x.Value,
StringComparer.OrdinalIgnoreCase);
newQuery.Remove("SearchTerm");
newQuery.Remove("SearchText");
newQuery.Remove("Skip");
if (!string.IsNullOrEmpty(SearchTerm))
newQuery["SearchTerm"] = new StringValues(SearchTerm);
if (!string.IsNullOrEmpty(SearchText))
newQuery["SearchText"] = new StringValues(SearchText);
newQuery.Remove("FilterCommand");
var path = (request.PathBase + request.Path).ToString();
var newUrl = QueryHelpers.AddQueryString(path, newQuery);
return new LocalRedirectResult(newUrl);
}
public Dictionary PaginationQuery { get; set; }
[ValidateNever]
[BindingBehavior(BindingBehavior.Never)]
public abstract int CurrentPageCount { get; }
}
}