@typeparam TNode

@*
 *                                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.
 *@

<style>

    .drag-drop-li {
        list-style-type: none;
    }
     
</style>

<ul ondragover="event.preventDefault();" class="@Class">
    @if (Value != null)
    {
        foreach (var item in Value)
        {
            if (item != null)
            {
                <li draggable="true"
                    class="@LiClass"
                    tabindex="1"
                    @ondrop="@(() => Drop(item))"
                    @ondrag="@(() => StartDrag(item))">
                    @ItemTemplate?.Invoke(item)
                </li>
            }
            else
            {
                <li>NULL</li>
            }
        }
    }
</ul>

@code
                                                                {
    [Parameter] public List<TNode>?               Value        { get; set; }
    [Parameter] public EventCallback<List<TNode>> ValueChanged { get; set; }
    [Parameter] public RenderFragment<TNode>?     ItemTemplate { get; set; }
    [Parameter] public string                     Class        { get; set; } = "";
    [Parameter] public string                     LiClass      { get; set; } = "drag-drop-li";

    private int _currentIndex;

    private void StartDrag(TNode item)
    {
        _currentIndex = GetIndex(item);
    }

    private int GetIndex(TNode item) => Value?.IndexOf(item) ?? -1;

    private async void Drop(TNode item)
    {
        try
        {
            if ( item == null || Value == null )
                return;

            var index = GetIndex(item);
            if (index < 0)
                return;

            // get current item
            var current = Value[_currentIndex];
            // remove TNode from current index
            Value.RemoveAt(_currentIndex);
            Value.Insert(index, current);

            // update current selection
            _currentIndex = index;

            await InvokeAsync(StateHasChanged);
            await ValueChanged.InvokeAsync(Value);
        }
        catch (Exception)
        {
            // ignore
        }
    }
}