@using System.Dynamic
@using System.Reflection
@using log4net
@using Rms.Risk.Mango.Pivot.Core.Models
@using Rms.Risk.Mango.Pivot.Core

@*
 *                                dbMango
 *
 * Copyright 2025 Deutsche Bank AG
 * SPDX-License-Identifier: Apache-2.0
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *@

<div class="@Class">
    <PivotTableComponent @ref="PivotTable"
        @bind-PivotData="PivotData"
        Rows="Rows"
        ExtraFilter="@ExtraFilter"
        PivotService="@PivotService"
        HandleCellClick="@HandleCellClick"
        GetColumnDescriptor="@GetColumnDescriptor"
        Collections="@Collections"
    />
</div>

@code
{
    private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod()!.DeclaringType!);

    [Parameter]
    public IPivotTableDataSource? PivotService
    {
        get;
        set
        {
            field = value;
            UpdatePivot();
        }
    }

    [Parameter] public Func<DynamicObject, string, Task<bool>>             HandleCellClick     { get; set; } = (_, _) => Task.FromResult(false);
    [Parameter] public Func<string /*columnName*/, PivotColumnDescriptor?> GetColumnDescriptor { get; set; } = _ => null;

    [Parameter] public bool EnableAutoUpdate { get; set; } = true;
    [Parameter] public int Rows { get; set; } = 35;

    [Parameter]
    public bool Transpose
    {
        get;
        set
        {
            field = value;
            UpdatePivot();
        }
    } = false;

    [Parameter] public string Class { get; set; } = "";

    [Parameter]
    public string? CollectionName
    {
        get;
        set
        {
            if (string.Equals(field, value))
                return;

            field = value;
            UpdatePivot();
        }
    }

    [Parameter]
    public string? PivotName
    {
        get;
        set
        {
            if (string.Equals(field, value))
                return;

            field = value;
            UpdatePivot();
        }
    }

    [Parameter]
    public FilterExpressionTree.ExpressionGroup? ExtraFilter
    {
        get;
        set
        {
            if (value == null)
            {
                field = null;
                return;
            }

            if (field == value)
                return;

            field = value;
            UpdatePivot();
        }
    }

    [Parameter]
    public List<GroupedCollection> Collections
    {
        get;
        set
        {
            field = value;
            UpdatePivot();
        }
    } = [];

    [Parameter]
    public IPivotedData? PivotData
    {
        get;
        set
        {
            if (field == value)
                return;

            field = value;
            PivotDataChanged.InvokeAsync(field);
            InvokeAsync(StateHasChanged);
        }
    }

    [Parameter] public EventCallback<IPivotedData> PivotDataChanged { get; set; }


    private readonly FilterExpressionTree.ExpressionGroup _noFilter = new();

    private PivotTableComponent? PivotTable
    {
        get;
        set
        {
            field = value;
            UpdatePivot();
        }
    }

    private async void UpdatePivot()
    {
        try
        {
            await InvokeAsync(StateHasChanged);

            if ( !EnableAutoUpdate )
                return;

            await Refresh();
        }
        catch (Exception e)
        {
            _log.Error(e.Message, e);
        }
    }

    public async Task Refresh()
    {
        if (PivotName == null || CollectionName == null || PivotService == null || PivotTable == null)
            return;

        if (Collections.Count == 0)
        {
            var cts         = new CancellationTokenSource(TimeSpan.FromSeconds(10));
            var collections = await PivotService.GetAllMeta(token: cts.Token);
            Collections.Clear();
            Collections.AddRange(collections);
        }

#pragma warning disable BL0005

        // WARNING: using hack here to set PivotTable.SelectedXXX parameters.
        // Usual way via StateHasChanged is not working due to a race condition
        // Somehow it related to multiple SimplePivotComponent on one page

        PivotTable.SelectedPivotNode      = new() {Text = "", Pivot = new() };
        PivotTable.SelectedCollectionNode = Collections.FirstOrDefault(x => x.CollectionNameWithPrefix == CollectionName);
        if ( PivotTable.SelectedCollectionNode != null )
            PivotTable.SelectedPivotNode = PivotTable.SelectedCollectionNode.Pivots.FirstOrDefault(x => x.Pivot.Name == PivotName);

        await InvokeAsync(StateHasChanged);

        if (PivotTable.SelectedPivotNode == null)
            return;
#pragma warning restore BL0005

        await PivotTable.RunPivot(PivotTable.SelectedPivotNode.Pivot, ExtraFilter ?? _noFilter, addToNavigation: false);

        if ( Transpose )
        {
            PivotData = SimpleTranspose.Transpose(PivotData);
        }
    }
}
