using System; using System.Collections.Generic; using System.Linq; using System.Threading.Tasks; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.RazorPages; using HaDocument.Interfaces; using System.Collections.Immutable; using HaDocument.Models; using HaDocument.Comparers; using HaXMLReader.EvArgs; using HaLive.Models; using HaXMLReader.Interfaces; using System.Collections.Concurrent; namespace HaLive.Pages { public class IndexModel : PageModel { const int MAX_SRESULTS = 1000; const int MINLETTPG = 90; [BindProperty(SupportsGet = true)] public string fdletter { get; set; }= ""; [BindProperty(SupportsGet = true)] public string search { get; set; } = ""; [BindProperty(SupportsGet = true)] public string person { get; set; } = ""; [BindProperty(SupportsGet = true)] public string havolume { get; set; } = ""; [BindProperty(SupportsGet = true)] public string hapage { get; set; } = ""; [BindProperty(SupportsGet = true)] public string selpage { get; set; } = ""; public enum IndexState { Initial, Search, ZHLookup, PersonLookup } public enum IndexFailState { None, SearchTooManyResults, SearchNoResult, ZHNotFound, LetterNotFound } public int cleanpage { get; set; } = 0; public IndexState State { get; set; } = IndexState.Initial; public IndexFailState FailState { get; set; } = IndexFailState.None; public List>> Result = null; public ImmutableSortedSet SelectedPersons = null; private ILibrary _lib; private IReaderService _readerService; public IndexModel(ILibrary lib, IReaderService readerservice) { _lib = lib; _readerService = readerservice; PrepareData(); } private void PrepareData() { // Create a list of persons var _SelectedPersons = new List(100); foreach (var letter in _lib.MetasByDate) { foreach (var sender in letter.Senders) { var p = _lib.Persons[sender]; if (!_SelectedPersons.Contains(p)) { _SelectedPersons.Add(p); } } foreach (var receiver in letter.Receivers) { var p = _lib.Persons[receiver]; if (!_SelectedPersons.Contains(p)) { _SelectedPersons.Add(p); } } } SelectedPersons = _SelectedPersons.ToImmutableSortedSet(new PersonComparer()); } public IActionResult OnGet() { if (!String.IsNullOrWhiteSpace(fdletter)) { if (_lib.Metas.Where(x => x.Value.Autopsic == fdletter).Any()) return Redirect("/Briefe/" + fdletter); else FailState = IndexFailState.LetterNotFound; State = IndexState.Initial; return Default(); } // State detection and Execution if (!String.IsNullOrWhiteSpace(search)) { State = IndexState.Search; return Search(); } else if (!String.IsNullOrWhiteSpace(person)) { State = IndexState.PersonLookup; return PersonLookup(); } else if (!String.IsNullOrWhiteSpace(havolume) || !String.IsNullOrWhiteSpace(hapage)) { State = IndexState.ZHLookup; return ZHLookup(); } else { State = IndexState.Initial; return Default(); } } internal ActionResult Search() { var ret = new ConcurrentBag(); var searchin = _lib.MetasByDate.Select(x => new DocumentSearchResult(x)).ToImmutableSortedSet(new LetterComparer()); var cnt = 0; //TODO: Nicht in threads manipulieren Parallel.ForEach (searchin, (letter, state) => { if (cnt > 1000) { FailState = IndexFailState.SearchTooManyResults; state.Break(); } var x = new DocumentSearch(letter, _readerService.RequestStringReader(_lib.Letters[letter.MetaData.Index].Element), search); cnt = cnt + x.Act().Results.Count; if (x._searchResult.Results.Count > 0 ) ret.Add(x._searchResult); }); if (ret.Count() == 0) { FailState = IndexFailState.SearchNoResult; } return Execute(ret); } internal ActionResult ZHLookup() { var ret = ImmutableSortedSet.CreateBuilder(new LetterComparer()); ImmutableDictionary> pagedic; var selvolume = _lib.Structure.TryGetValue(havolume.Trim(), out pagedic); if (selvolume) { ImmutableDictionary linedic; var selpage = pagedic.TryGetValue(hapage.Trim(), out linedic); if (selpage) { foreach (var entry in linedic) { ret.Add(_lib.MetasByDate.Where(x => x.Index == entry.Value).Select(x => new DocumentSearchResult(x)).First()); } if (ret.Count == 1) { return Redirect("/Briefe/" + ret.First().MetaData.Autopsic + "#" + hapage + "-1"); } } else { FailState = IndexFailState.ZHNotFound; return Execute(ret); } } else { return FatalError(); } return Execute(ret); } internal ActionResult PersonLookup() { return Execute(_lib.MetasByDate .Where(x => x.Senders.Contains(person) || x.Receivers.Contains(person)) .Select(x => new DocumentSearchResult(x))); } internal ActionResult Default() { return Execute(_lib.MetasByDate .Select(x => new DocumentSearchResult(x))); } internal ActionResult Execute(IEnumerable _result) { if (_result == null) FatalError(); var res = _result.OrderBy(x => x, new LetterComparer()).ToLookup(x => x.MetaData.Sort.Year, x => x); return Paginate(res); } internal ActionResult Paginate(ILookup _result) { if (_result == null) return Return(); var curr = new List>(); Result = new List>>(); foreach (var elem in _result) { curr.Add(elem); if (curr.SelectMany(x => x).Count() > MINLETTPG || elem == _result.Last()) { Result.Add(new List>(curr)); curr.Clear(); } } if (!String.IsNullOrWhiteSpace(selpage)) { int no; var isNo = Int32.TryParse(selpage, out no); if (!isNo || Result.Count < no || no <= 0) { return FatalError(); } else { cleanpage = no - 1; } } else { selpage = "1"; } return Return(); } internal ActionResult FatalError() { Response.StatusCode = 404; return RedirectToPage("/Error"); } internal ActionResult Return() { return Page(); } } }