@page "/"
@inject NavigationManager navigator
@inject HttpClient httpClient
@inject Blazored.LocalStorage.ILocalStorageService localStorage
@inject SpeechSynthesis SpeechSynthesis

<PageTitle>Index</PageTitle>

<MudContainer Class="align-center justify-center d-flex">
    <MudContainer Style="width: 400px">
        <MudSelect Class="pt-12" @bind-Value=selectedChunk TextChanged="SelectedChunk" select T=int Label="Chunk" Variant="Variant.Filled" AnchorOrigin="Origin.BottomCenter">
            @for (int i = 0; i < numOfChunks; i++)
            {
                <MudSelectItem T="int" Value="@i" />
            }
        </MudSelect>
        <MudContainer Class="justify-center d-flex pt-4" Style="width:300px">
            <MudButton Variant="Variant.Filled" OnClick=StartLearning Color="Color.Primary">@((!continueDataExists) ? "Start learning!" : "Start new!")</MudButton>
            <MudStack Spacing="0" Class="pa-0 pl-2 ma-0">
                @if (continueDataExists)
                {
                    <MudButton Class="pb-0 px-0" Variant="Variant.Filled" Color="Color.Success" OnClick="ContinueLearning" Disabled="@(!continueDataExists)">
                        <MudStack Class="mud-width-full" Spacing="1">
                            <MudContainer Class="px-2">
                                <MudStack Class="justify-center d-flex" Row=true Spacing="1">
                                    <MudText>@($"Continue: {continueCharectersLeft}")</MudText>
                                    <MudIconButton Class="pa-0 ma-0" OnClick="DeleteContinueData" Variant=Variant.Filled Color="Color.Error" Icon="@Icons.Material.Filled.Close"></MudIconButton>
                                </MudStack>
                            </MudContainer>
                            <MudProgressLinear Class="pa-0 ma-0" Color="Color.Warning" Size="Size.Small" Value="@(((float)continueCharectersLeft/(float)chunkSize))" />
                        </MudStack>
                    </MudButton>
                }
            </MudStack>
        </MudContainer>

        <MudContainer Class="justify-center d-flex">
            <MudStack Class="pt-4 " Spacing="0">
                <MudContainer Class="pa-4">
                    <MudText Typo="Typo.h6" Class="fw-bold">Modifiers:</MudText>
                    <MudCheckBox Class="mr-6" @bind-Checked="@IgnoreTone" Label="Ignore pinyin tones" Color="Color.Primary"></MudCheckBox>
                    <MudCheckBox Class="mr-6" @bind-Checked="@UseChangingFonts" Label="Changing fonts" Color="Color.Primary"></MudCheckBox>
                </MudContainer>
            </MudStack>
        </MudContainer>

        <MudContainer Class="pt-4 justify-center d-flex">
            @if (Charecters != null)
            {
                <MudPaper Class="overflow-scroll rounded-lg" Style="height: 40vh;" Elevation="1">
                    <MudDataGrid Style="" SortMode="SortMode.None" Height="500" FixedHeader=true Items="@Charecters" Breakpoint="Breakpoint.None">
                        <Columns>
                            <PropertyColumn Property="x => x.charcter" Title="CChar" />
                            <PropertyColumn Property="x => x.pinyin" Title="Pinyin" />
                        </Columns>
                    </MudDataGrid>
                </MudPaper>
            }
        </MudContainer>

        <MudContainer Class="justify-center d-flex pt-4">
            <MudButton Class="mt-1 mb-7" Variant="Variant.Filled" Color="Color.Secondary" Disabled="@(isLoading || isSavedLocally)" OnClick="LoadAllChunksIntoLocalStorage">
                @if (!isSavedLocally)
                {
                    @if (isLoading)
                    {
                        <MudText>@($"{savedChunks}/{numOfChunks}")</MudText>
                        <MudProgressCircular Class="pl-8 ms-n1 mr-2" Size="Size.Small" Indeterminate="true" />
                    }
                    else
                    {
                        <MudText>Load chunks to local storage</MudText>
                        <MudIcon Icon="@Icons.Material.Rounded.Send" Class="mr-1" />
                    }
                }
                else
                {
                    <MudText>Chunks are saved locally</MudText>
                }
            </MudButton>
        </MudContainer>
        <MudContainer Class="justify-center d-flex pt-4">
            <MudButton OnClick="async ()=>{await localStorage.ClearAsync(); navigator.NavigateTo(string.Empty, true);}" Variant="Variant.Outlined" Color="Color.Tertiary">Delete local storage</MudButton>
        </MudContainer>
    </MudContainer>
</MudContainer>

@code{
    int numOfChunks = 197; //Exclusive index 0
    int selectedChunk = 0;
    int savedChunks = 0;
    const int chunkSize = 50;

    bool isLoading = false;
    bool isSavedLocally = false;
    bool continueDataExists = false;
    int continueCharectersLeft = -1;

    private bool ignoreTone;

    public bool IgnoreTone
    {
        get { return ignoreTone; }
        set 
        {
            ignoreTone = value;
            SetIgnoreTone();
        }
    }
    
    private bool useChangingFonts;

    public bool UseChangingFonts
    {
        get { return useChangingFonts; }
        set 
        {
            useChangingFonts = value;
            SetChangingFonts();
        }
    }



    protected async override Task OnInitializedAsync()
    {
        if (await localStorage.ContainKeyAsync("Normalized_chunk_001.json")) 
            isSavedLocally = true;

        continueDataExists = await localStorage.ContainKeyAsync("ContinueData");

        SelectedChunk();
        StateHasChanged();
    }

    async void StartLearning()
    {
        await localStorage.SetItemAsync("SelectedChunk", selectedChunk);
        await localStorage.SetItemAsync("ContinueLearning", false);
        navigator.NavigateTo("/Learn");
    }

    async void ContinueLearning()
    {
        await localStorage.SetItemAsync("ContinueLearning", true);
        navigator.NavigateTo("/Learn");
    }

    async void DeleteContinueData()
    {
        string[] continueDataKeys = { "ContinueLearning", "ContinueData", "ContinueCharectersLeft" };
        await localStorage.RemoveItemsAsync(continueDataKeys);
        continueDataExists = false;

        StateHasChanged();
    }

    CChar[]? Charecters;
    async void SelectedChunk()
    {
        if (await localStorage.ContainKeyAsync("Normalized_chunk_001.json"))
            isSavedLocally = true;

        if (!isSavedLocally)
            Charecters = await httpClient.GetFromJsonAsync<CChar[]>($"Data/Normalized_chunk_{selectedChunk.ToString("000")}.json");
        else
        {
            string json = await localStorage.GetItemAsync<string>($"Normalized_chunk_{selectedChunk.ToString("000")}.json");
            Charecters = JsonConvert.DeserializeObject<CChar[]>(json);
        }
        StateHasChanged();
    }

    async void SetIgnoreTone()
    {
        await localStorage.SetItemAsync("IgnoreTone", ignoreTone);
    }
    
    async void SetChangingFonts()
    {
        await localStorage.SetItemAsync("ChangingFonts", UseChangingFonts);
    }

    async Task LoadAllChunksIntoLocalStorage()
    {
        isLoading = true;
        string[] jsonChunks = new string[numOfChunks];

        Parallel.For(0, numOfChunks, async (i)=>
        {
            await Task.Delay(10*i);
            try
            {
                jsonChunks[i] = await httpClient.GetStringAsync($"Data/Normalized_chunk_{i.ToString("000")}.json");
            }
            catch (Exception)
            {
                await Task.Delay(100);
                jsonChunks[i] = await httpClient.GetStringAsync($"Data/Normalized_chunk_{i.ToString("000")}.json");
            }

            if (string.IsNullOrEmpty(jsonChunks[i])) throw new Exception("Couldn't load chunk: " + i);

            try
            {
                await localStorage.SetItemAsync($"Normalized_chunk_{i.ToString("000")}.json", jsonChunks[i]);
            }
            catch (Exception)
            {
                await Task.Delay(100);
                await localStorage.SetItemAsync($"Normalized_chunk_{i.ToString("000")}.json", jsonChunks[i]);
            }

            if (!await localStorage.ContainKeyAsync($"Normalized_chunk_{i.ToString("000")}.json")) throw new Exception("Couldn't save chunk: " + i);
        });

        while (jsonChunks.Any(x => x == null))
        {
            await Task.Delay(1);
            savedChunks = jsonChunks.Count(x=>x != null);
            StateHasChanged();
        }

        isLoading = false;
        isSavedLocally = true;
        StateHasChanged();
    }

    protected override async Task OnAfterRenderAsync(bool firstRender)
    {
        if (firstRender)
        {
            
        }

        if (continueDataExists)
        {
            continueCharectersLeft = await localStorage.GetItemAsync<int>("ContinueCharectersLeft");
        }

        if (await localStorage.ContainKeyAsync("IgnoreTone"))
        {
            ignoreTone = await localStorage.GetItemAsync<bool>("IgnoreTone");
        }
        
        if (await localStorage.ContainKeyAsync("ChangingFonts"))
        {
            UseChangingFonts = await localStorage.GetItemAsync<bool>("ChangingFonts");
        }
    }
}