using System;
using System.ComponentModel;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.Web;

using CommonHelpers.WASM;
using AFXUI;

using BookRegistry.Client.Shared;
using BookRegistry.Client.Pages;
using BookRegistry.Client.DB;

namespace BookRegistry.Client.Components {

//**************************************************************************************************
/// <summary>
/// BookCard-subpage component (in HomePage)
/// </summary>
public partial class BookCard: AComponent {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
static HomeService SRV => Services.HomeService;
//==================================================================================================
protected ElementReference? DescriptionTEXTAREA;
#nullable disable
protected AEditBox BookNameEdit,ISBNEdit,ReleaseYearEdit;
protected ADropDownList_IdName AuthorDDL,CategoryDDL,GenreDDL,PublisherDDL,SeriesDDL;
protected AButton ApplyButton,ShowErrorsButton;
protected AErrorList ErrorList;
#nullable restore
string? Description;
bool SubmissionEnabled,WasInputChanged;
//==================================================================================================
bool DisplayContent => ParentPage.IsOnBookCardSubpage;
//--------------------------------------------------------------------------------------------------

[CascadingParameter] HomePage? ParentPageN { get; set; }
[CascadingParameter] SelectBooks_Item? CurrentBookN { get; set; }
[CascadingParameter] GetBookSelectionCollections_Response? BookSelectionCollectionsN { get; set; }

/// <exception cref="InvalidOperationException" />
HomePage ParentPage =>
   ParentPageN ?? throw CascadingPropertyIsNull( nameof(ParentPage) );
/// <exception cref="InvalidOperationException" />
SelectBooks_Item CurrentBook =>
   CurrentBookN ?? throw CascadingPropertyIsNull( nameof(CurrentBook) );
/// <exception cref="InvalidOperationException" />
GetBookSelectionCollections_Response BookSelectionCollections =>
   BookSelectionCollectionsN ?? throw CascadingPropertyIsNull( nameof(BookSelectionCollections) );

static InvalidOperationException CascadingPropertyIsNull(string propertyName) =>
   HInvOpExceptionCreator.Create(
      "\"{0}\" cascading property is null (\"{1}\"-component).",
      propertyName, nameof(BookCard) );

//--------------------------------------------------------------------------------------------------

bool IsInEditMode => CurrentBook.NID.HasValue;
bool IsInAddingMode => !IsInEditMode;

bool IsForCorrection => ParentPage.IsForCorrection;
bool IsForReadOnly => !IsForCorrection;

string ApplyButtonText
{
   get {
      if (IsInAddingMode)
         return "ADD BOOK-RECORD";
      if (IsInEditMode)
         return "SAVE BOOK-DATA";
      throw HAssertionFailure.DEAD_BRANCH();
   }
}
string ApplyButtonTitle
{
   get {
      if (IsInAddingMode)
         return "Add new book to registry database";
      if (IsInEditMode)
         return "Save book data to registry database";
      throw HAssertionFailure.DEAD_BRANCH();
   }
}

string? InputChangeMessage =>
   WasInputChanged ? null :
   IsInEditMode ?
      "Nothing was corrected yet." :
      "Nothing was entered yet.";

//==================================================================================================

protected override void OnDispose()
{
   base.OnDispose();
   App.FocusChanged -= App_FocusChanged;
   App.OnKeyDown -= Window_OnKeyDown;
}

//==================================================================================================

protected override void OnInitialized() =>
go(()=>{
   base.OnInitialized();
   App.FocusChanged += App_FocusChanged;
   App.OnKeyDown += Window_OnKeyDown;
});

protected override void On_Load() =>
go(()=>{
   var colls = BookSelectionCollections;
   AuthorDDL   .SetItems( colls.Authors );
   CategoryDDL .SetItems( colls.Categories );
   GenreDDL    .SetItems( colls.Genres );
   PublisherDDL.SetItems( colls.Publishers );
   SeriesDDL   .SetItems( colls.Series );
   if ( IsInEditMode )
   {
      var book = CurrentBook;
      BookNameEdit   .SetText( book.Name );
      ISBNEdit       .SetText( book.ISBN );
      ReleaseYearEdit.SetText( book.ReleaseYear.ToString() );
      Description = book.Description;
      AuthorDDL      .SetSelectedId( book.AuthorId );
      CategoryDDL    .SetSelectedId( book.CategoryId );
      GenreDDL       .SetSelectedId( book.GenreId );
      PublisherDDL   .SetSelectedId( book.PublisherId );
      SeriesDDL      .SetSelectedId( book.SeriesId );
   }
   StateHasChanged();
});

protected override Task On_AfterLoad_A() =>
go(async()=>{
   UPage.DeferredUnscroll();
   BookNameEdit.DeferredFocus();
   await Task.Delay(0);
});

//==================================================================================================

async Task<bool> ESC_PrepareToSaving_A()
{
   ValidateInput_EnableSubmission( true );
   return
      await ESC_CheckInput_A( BookNameEdit ) &&
      await ESC_CheckInput_A( ISBNEdit ) &&
      await ESC_CheckInput_A( ReleaseYearEdit ) &&

      await ESC_CheckInput_A( AuthorDDL ) &&
      await ESC_CheckInput_A( CategoryDDL ) &&
      await ESC_CheckInput_A( GenreDDL ) &&
      await ESC_CheckInput_A( PublisherDDL ) &&
      await ESC_CheckInput_A( SeriesDDL ) &&

      !ErrorList.HasErrors;
}

//==================================================================================================

void CancelButton_OnClick() =>
GO(()=>{
   ParentPage.SwitchToMainContent();
});

void SelectDescriptionButton_OnClick() =>
GO(()=>{
   DescriptionTEXTAREA.FocusSelect();
});

void Description_OnInput(ChangeEventArgs e) =>
go(()=>{
   Description = e.Value.NN().ToString();
   InputField_VMClear( true );
});

Task ShowFieldErrors_OnClick_A() =>
GO(async()=>{
   if (await ESC_PrepareToSaving_A())
      using (new SaveFocus())
         await ESC_ShowInputCorrectMsg_A();
});

void Window_OnKeyDown(KeyboardEventArgs e) =>
go(()=>{
   if ( UInput.IsPureKey( e, "F2" ) && ApplyButton.IsEnabled )
      ApplyButton.Click();
   else
   if ( UInput.IsPureKey( e, "F9" ) && ShowErrorsButton.IsEnabled )
      ShowErrorsButton.Click();
});

Task ApplyButton_OnClick_A() =>
GO(async()=>{if (await ESC_PrepareToSaving_A())
using (var fo=ForeOperation.WithSaveFocus()){
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   var bookSavingInput = IsInEditMode ?
      (BookSaving_Input)new UpdateBook_Input() { ID = CurrentBook.ID } :
      (BookSaving_Input)new AddBook_Input();
   FILL_BOOK_SAVING( bookSavingInput );
   var sir = IsInEditMode ?
      (SimpleSIR)(await SRV.ESC_UpdateBook_A( (UpdateBook_Input)bookSavingInput ) ) :
      (SimpleSIR)(await SRV.ESC_AddBook_A( (AddBook_Input)bookSavingInput ) );
   if ( WasAbandoned_Notify_Deactivate( sir ) )
      return;
   if ( await ESC_HasRequestError_ShowError_A( sir ) )
      return;
   if ( IsInEditMode )
      COPY_TO_CURRENT_BOOK( bookSavingInput );
   fo.SaveFocus = false;   
   ParentPage.SwitchToMainContent( IsInEditMode ? BookListCorrection.ApplyEditChange : 0 );
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
   void FILL_BOOK_SAVING(BookSaving_Input inp)
   {
      inp.ISBN = HString.TrimOrNull( ISBNEdit.Text );
      inp.Name = HString.TrimOrNull( BookNameEdit.Text );
      inp.ReleaseYear = ReleaseYearEdit.HasText ?
         (int?)HInt32.ParseInvariant( ReleaseYearEdit.Text ) : null;
      inp.AuthorId    = AuthorDDL    .SelectedId.V();
      inp.PublisherId = PublisherDDL .SelectedId.V();
      inp.SeriesId    = SeriesDDL    .SelectedId.V();
      inp.CategoryId  = CategoryDDL  .SelectedId.V();
      inp.GenreId     = GenreDDL     .SelectedId.V();
      inp.Description = HString.TrimEndOrNull( Description );
   }
   void COPY_TO_CURRENT_BOOK(BookSaving_Input inp)
   {
      var cp = CurrentBook;
      cp.Name           = inp.Name;
      cp.ISBN           = inp.ISBN;
      cp.ReleaseYear    = inp.ReleaseYear;
      cp.AuthorId       = inp.AuthorId;
      cp.PublisherId    = inp.PublisherId;
      cp.SeriesId       = inp.SeriesId;
      cp.CategoryId     = inp.CategoryId;
      cp.GenreId        = inp.GenreId;
      cp.AuthorName     = AuthorDDL.SelectedName ?? "";
      cp.PublisherName  = PublisherDDL.SelectedName ?? "";
      cp.SeriesName     = SeriesDDL.SelectedName ?? "";
      cp.CategoryName   = CategoryDDL.SelectedName ?? "";
      cp.GenreName      = GenreDDL.SelectedName ?? "";
      cp.Description    = inp.Description;
   }
//-- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
}});

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // BookCard
//**************************************************************************************************

} // BookRegistry.Client.Components
