@inherits ViewBase

@code {
    private Dictionary<string, string> AllTrackSet;

    private string searchExpression { get => LocalStorage.Get<string>(); set => LocalStorage.Set(value); }
    private string searchTrackSetKey { get => LocalStorage.Get<string>() ?? "main"; set => LocalStorage.Set(value); }
    private int searchLimitCount { get => LocalStorage.Get<int?>() ?? 20; set => LocalStorage.Set(value); }

    private bool isSearching = false;
    private ProgressBar searchProgressBar;

    private static string resultText;
    private static IGrouping<FeDisc, FeTrack>[] resultEntries;

    private DiscDialog dlgDisc;
    private PlaylistAddDialog dlgPlaylistAdd;
}

<DiscDialog @ref="dlgDisc" Disc="CurrentDisc"></DiscDialog>
<PlaylistAddDialog @ref="dlgPlaylistAdd"></PlaylistAddDialog>

<div class="row">
    <div class="col-12">
        <fieldset class="border rounded-3 p-2">
            <legend class="float-none w-auto px-2 d-flex flex-row align-items-center">
                <span>Filter</span>
            </legend>
            <div class="input-group">
                <div class="form-floating">
                    <InputText type="search" class="form-control" placeholder="Search expression"
                               Value="@searchExpression"
                               ValueExpression="@(()=>searchExpression)"
                               @oninput="SearchChanged"
                               onsearch="@SearchGo">
                    </InputText>
                    <label>Search expression</label>
                </div>
                <button @onclick="@SearchGo" class="btn btn-outline-primary" type="button">Search</button>
            </div>
            <div class="row mt-3">
                <label for="staticEmail" class="col-sm-2 col-form-label">Track set</label>
                <div class="col-sm-10">
                    <InputRadioGroup @bind-Value="TrackSetKeyProperty">
                        <div class="btn-group" role="group" aria-label="Basic radio toggle button group">
                            @foreach (var item in AllTrackSet.KeepNoEmpty().WithIndex())
                            {
                                <InputRadio class="btn-check" id="@("stk-"+item.index)" Value="item.item.Key"></InputRadio>
                                <label class="btn btn-outline-primary" for="@("stk-"+item.index)">@(item.item.Value)</label>
                            }
                        </div>
                    </InputRadioGroup>
                </div>
            </div>
            <div class="row mt-3">
                <label for="staticEmail" class="col-sm-2 col-form-label">Result count</label>
                <div class="col-sm-10">
                    <InputRadioGroup @bind-Value="ResultCountProperty">
                        <div class="btn-group" role="group" aria-label="Basic radio toggle button group">
                            @foreach (var lc in new[] { 20, 50, 100, 200 })
                            {
                                <InputRadio class="btn-check" id="@($"limit-count-{lc}")" Value="@lc"></InputRadio>
                                <label class="btn btn-outline-primary" for="@($"limit-count-{lc}")">@lc</label>
                            }
                        </div>
                    </InputRadioGroup>
                </div>
            </div>
            @*<div class="row mt-3">
            <label for="staticEmail" class="col-sm-2 col-form-label">Debug</label>
            <div class="col-sm-10">
            <button class="btn btn-primary" @onclick="()=>isSearching=true">Show progressbar</button>
            </div>
            </div>*@
        </fieldset>
    </div>
</div>

@if (isSearching)
{
    <div class="row mt-4">
        <div class="col-12">
            <div class="btn-group w-100">
                <ProgressBar @ref="searchProgressBar" Throttle="333" class="btn border w-75"></ProgressBar>
                <button class="btn border btn-danger" @onclick="()=>isSearching=false">Stop search</button>
            </div>
        </div>
    </div>
}

<div class="row mt-3">
    <div class="col-12">
        <fieldset class="border rounded-3 p-2">
            <legend class="float-none w-auto px-2 d-flex flex-row align-items-center">
                <span>Result</span>
            </legend>

            <div class="mb-3 text-center">@resultText</div>

            @if (resultEntries?.Length > 0)
            {
                foreach (var item in resultEntries)
                {
                    var disc = item.Key;

                    <div class="table-responsive">
                        <table class="table w-100">
                            <tbody>
                                <tr class="table-primary">
                                    <td><img src="@disc.CoverPath" style="height:50px" /></td>
                                    <td colspan="2" class="w-100">
                                        <div class="text-nowrap">@item.Key.Name</div>
                                        <div class="text-nowrap text-muted">@item.Key.Lib.Name</div>
                                    </td>
                                    <td colspan="2" class="text-end">
                                        <button class="btn btn-primary" @onclick="()=>dlgDisc.Show(disc)">
                                            <i class="bi bi-window-stack"></i>
                                        </button>
                                    </td>
                                </tr>

                                @foreach (var tr in item.OrderBy(p => p.Name))
                                {
                                    <tr class="mouse-hilight">
                                        <td class="align-middle"><FileIcon Track="@tr" ShowParam="true"></FileIcon></td>
                                        <td class="w-100 text-nowrap">
                                            <div>
                                                <a href="@tr.Path" target="@FnzConst.PlayPageTarget">
                                                    <HighLightKeyword Text="@tr.GetTitleOrFilename()" Keywords="@(new []{ searchExpression})"></HighLightKeyword>
                                                </a>
                                            </div>
                                            <div class="text-nowrap text-muted">@tr.Tag?.Artist</div>
                                        </td>
                                        <td>
                                            <div class="text-nowrap">@tr.Tag.Duration.SecondToDur()</div>
                                            <div class="text-nowrap text-muted">@tr.Tag.Length.BytesToFileSize()</div>
                                        </td>
                                        <td class="text-center align-middle">
                                            <button type="button" class="btn btn-link" style="padding:0.1rem" @onclick="()=>dlgPlaylistAdd.Show(tr)">
                                                <i class="bi bi-folder-plus"></i>
                                            </button>
                                        </td>
                                    </tr>
                                }
                            </tbody>
                        </table>
                    </div>
                }
            }
        </fieldset>
    </div>
</div>

@code {
    private async Task SearchGo()
    {
        isSearching = true;
        StateHasChanged();

        await Task.Delay(1);

        var filteredList = new List<FeTrack>(searchLimitCount);
        var matchedCount = 0;
        var flagPlus = false;

        var filters = new List<Func<FeTrack, bool>> { p => p.TrackSetKey == searchTrackSetKey };
        //TODO: Expression implement
        if (string.IsNullOrEmpty(searchExpression) == false)
        {
            filters.Add(p => p.GetTitleOrFilename().Contains(searchExpression, StringComparison.OrdinalIgnoreCase));
        }

        for (var i = 0; i < DataSet.AllTracks.Length && isSearching; i++)
        {
            var item = DataSet.AllTracks[i];
            if (filters.All(p => p(item)))
            {
                ++matchedCount;
                if (filteredList.Count < searchLimitCount)
                {
                    filteredList.Add(item);
                }
                else if (matchedCount >= searchLimitCount * 2)
                {
                    flagPlus = true;
                    break;
                }
            }
            await searchProgressBar.SetProgress((float)i / DataSet.AllTracks.Length, $"Searching {i + 1}/{DataSet.AllTracks.Length} matched:{matchedCount}");
        }

        //TODO: search in disc name

        resultText = $"Result for {searchExpression.NullOrEmptyEscape("<NONE>")} on {DataSet.AllTracksSet.Where(p => p.Key == searchTrackSetKey).Select(p => p.Name).FirstOrDefault() ?? "?"} limit {searchLimitCount} of {matchedCount}{(flagPlus ? "+" : "")}";

        resultEntries = filteredList
            .GroupBy(p => p.Disc)
            .ToArray();

        isSearching = false;
        StateHasChanged();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        await base.OnAfterRenderAsync(firstRender);
        if (firstRender)
        {
            AllTrackSet = DataSet.AllTracksSet.GroupBy(p => p.Key).ToDictionary(p => p.Key, p => p.First().Name);
            if (resultEntries == null) await SearchGo();
            else StateHasChanged();
        }
    }

    private void SearchChanged(ChangeEventArgs e)
    {
        searchExpression = e.Value.ToString().Trim();
    }

    public string TrackSetKeyProperty
    {
        get => searchTrackSetKey;
        set
        {
            if (searchTrackSetKey == value) return;
            searchTrackSetKey = value;
            SearchGo();
        }
    }

    public int ResultCountProperty
    {
        get => searchLimitCount;
        set
        {
            if (searchLimitCount == value) return;
            searchLimitCount = value;
            SearchGo();
        }
    }
}
