using Microsoft.AspNetCore.Components;
using Microsoft.JSInterop;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Bootstrap
{
    public partial class OffCanvas : IAsyncDisposable
    {
        private Guid _id;

        [Parameter] public RenderFragment? ChildContent { get; set; }
        [Parameter] public string Title { get; set; } = String.Empty;
        [Parameter] public OffCanvasPosition Position { get; set; } = OffCanvasPosition.End;
        [Parameter] public bool Show { get; set; }        
        [Parameter] public EventCallback<bool> ShowChanged { get; set; }
        [Parameter] public OffCanvasOptions Options { get; set; } = new OffCanvasOptions();
        [Parameter] public string SubClass { get; set; } = string.Empty;

        private IJSObjectReference? jsModule { get; set; }
        private DotNetObjectReference<OffCanvas> objRef;        
        private bool _preventParameters = false;

        public OffCanvas()
        {
            _id = Guid.NewGuid();
            objRef = DotNetObjectReference.Create(this);
        }

        protected override async Task OnParametersSetAsync()
        {
            if (_preventParameters) return;
            _preventParameters = true;            
            
            if (Show)
            {
                await ShowCanvas();
            }
            else
            {
                await HideCanvas();
            }
            _preventParameters = false;
        }

        protected override async Task OnInitializedAsync()
        {
            jsModule = await jsRuntime.InvokeAsync<IJSObjectReference>("import", "./_content/Bootstrap/bootstrap.offcanvas.js");
            await Setup();
        }

        public async Task Setup()
        {
            if (jsModule is not null)
            {
                await jsModule.InvokeVoidAsync("setup", _id, Options.ToJSON(), objRef);
            }
        }

        public async Task Destroy()
        {
            if (jsModule is not null)
            {
                try
                {
                    await jsModule.InvokeVoidAsync("destroy", _id);
                    await jsModule.DisposeAsync();
                }
                catch (TaskCanceledException)
                {
                }
                catch (JSDisconnectedException)
                {
                }
            }
        }

        private async Task Update()
        {
            if (jsModule is not null)
            {
                await jsModule.InvokeVoidAsync("update", _id, Options.ToJSON(), objRef);
            }
        }

        private async Task ShowCanvas()
        {
            if (jsModule is not null)
            {
                await jsModule.InvokeVoidAsync("show", _id);
            }
        }

        private async Task HideCanvas()
        {
            if (jsModule is not null)
            {
                await jsModule.InvokeVoidAsync("hide", _id);
            }
        }

        public async ValueTask DisposeAsync()
        {
            await Destroy();
        }

        public string GetOffCanvasPosition()
        {
            return Position switch
            {
                OffCanvasPosition.Top => "offcanvas-top",
                OffCanvasPosition.End => "offcanvas-end",
                OffCanvasPosition.Start => "offcanvas-start",
                OffCanvasPosition.Bottom => "offcanvas-bottom",
                _ => "offcanvas-end",
            };
        }

        [JSInvokable]
        public async Task OnHidden()
        {
            _preventParameters = true;
            await ShowChanged.InvokeAsync(false);
            _preventParameters = false;
        }

        [JSInvokable]
        public async Task OnShown()
        {
            _preventParameters = true;
            await ShowChanged.InvokeAsync(true);
            _preventParameters = false;
        }
    }
}
