using Borepin.ViewModel;
using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows.Input;
using Prism.Commands;
using Prism.Navigation;
using Borepin.Base;
using FabAccessAPI.Schema;
using Prism.Services;
using System;
using NaturalSort.Extension;
using System.Linq;
using Borepin.Service;
using static FabAccessAPI.Schema.Machine;
using Borepin.Model;

namespace Borepin.PageModel
{
    public class MachineListPageModel : ConnectionModelBase
    {
        #region Constructors
        public MachineListPageModel(INavigationService navigationService, IPageDialogService pageDialogService, IAPIService apiService) : base(navigationService, pageDialogService, apiService)
        {
            ScanCodeCommand = new DelegateCommand(async () => await ScanCodeCommandExecute().ConfigureAwait(false));
            RefreshCommand = new DelegateCommand(async ()=> await RefreshCommandExecute().ConfigureAwait(true));
        }
        #endregion

        #region Data
        public override async Task LoadAPIData()
        {
            IReadOnlyList<Machine> machine_list = await _API.Session.MachineSystem.Info.GetMachineList().ConfigureAwait(false);

            await _CreateMachineList(new List<Machine>(machine_list)).ConfigureAwait(false);
        }

        private async Task _CreateMachineList(List<Machine> machine_list)
        {
            List<Task> tasks = new List<Task>();

            List<MachineViewModelListGroup> viewmodel_group_list = new List<MachineViewModelListGroup>();
            MachineViewModelListGroup viewmodel_group_inusebyme = new MachineViewModelListGroup()
            {
                Category = Resources.Text.TextResource.InUseByMe,
            };
            MachineViewModelListGroup viewmodel_group_uncategorised = new MachineViewModelListGroup()
            {
                Category = String.Empty,
            };

            foreach (Machine machine in machine_list)
            {
                if (!((InUseInterface_Proxy)machine.Inuse).IsNull)
                {
                    MachineListItemViewModel new_viewmodel = new MachineListItemViewModel(_NavigationService, _PageDialogService)
                    {
                        IsInUseByMe = true,
                    };
                    tasks.Add(new_viewmodel.LoadInstance(machine));

                    new_viewmodel.Machine.Category = Resources.Text.TextResource.InUseByMe;
                    
                    viewmodel_group_inusebyme.Add(new_viewmodel);
                }
                else if (machine.Category == null)
                {
                    MachineListItemViewModel new_viewmodel = new MachineListItemViewModel(_NavigationService, _PageDialogService);
                    tasks.Add(new_viewmodel.LoadInstance(machine));

                    viewmodel_group_uncategorised.Add(new_viewmodel);
                }
                else
                {
                    MachineListItemViewModel new_viewmodel = new MachineListItemViewModel(_NavigationService, _PageDialogService);
                    tasks.Add(new_viewmodel.LoadInstance(machine));

                    MachineViewModelListGroup viewmodel_group = viewmodel_group_list.Find(x => string.Equals(x.Category, machine.Category, StringComparison.Ordinal));
                    if (viewmodel_group != null)
                    {
                        viewmodel_group.Add(new_viewmodel);
                    }
                    else
                    {
                        MachineViewModelListGroup new_viewmodel_group = new MachineViewModelListGroup()
                        {
                            Category = machine.Category,
                        };
                        new_viewmodel_group.Add(new_viewmodel);
                        viewmodel_group_list.Add(new_viewmodel_group);
                    }
                }
            }

            await Task.WhenAll(tasks).ConfigureAwait(false);

            viewmodel_group_inusebyme.Sort_Machines();
            viewmodel_group_uncategorised.Sort_Machines();
            foreach(MachineViewModelListGroup viewmodel_group in viewmodel_group_list)
            {
                viewmodel_group.Sort_Machines();
            }

            viewmodel_group_uncategorised.Category = String.Empty;
            List<MachineViewModelListGroup> viewmodel_group_list_sorted = new List<MachineViewModelListGroup>();
            if(viewmodel_group_inusebyme.Count != 0)
            {
                viewmodel_group_list_sorted.Add(viewmodel_group_inusebyme);
            }

            viewmodel_group_list_sorted.AddRange(new List<MachineViewModelListGroup>(viewmodel_group_list.OrderBy(x => x.Category, StringComparison.OrdinalIgnoreCase.WithNaturalSort())));

            if (viewmodel_group_uncategorised.Count != 0)
            {
                viewmodel_group_list_sorted.Add(viewmodel_group_uncategorised);
            }

            MachineListItemViewModel_List = viewmodel_group_list_sorted;
        }
        #endregion

        #region Fields
        private IList<MachineViewModelListGroup> _MachineListItemViewModel_List;
        public IList<MachineViewModelListGroup> MachineListItemViewModel_List
        {
            get => _MachineListItemViewModel_List;
            set => SetProperty(ref _MachineListItemViewModel_List, value);
        }
        #endregion

        #region Commands
        private ICommand _RefreshCommand;
        public ICommand RefreshCommand
        {
            get => _RefreshCommand;
            set => SetProperty(ref _RefreshCommand, value);
        }
        public async Task RefreshCommandExecute()
        {
            if(_API.IsConnected)
            {
                try
                {
                    await LoadAPIData().ConfigureAwait(true);
                }
                catch
                {
                    // TODO
                }
                
            }
        }

        private ICommand _ScanCodeCommand;
        public ICommand ScanCodeCommand
        {
            get => _ScanCodeCommand;
            set => SetProperty(ref _ScanCodeCommand, value);
        }
        public async Task ScanCodeCommandExecute()
        {
            IsBusy = true;

            NavigationParameters parameters = new NavigationParameters()
            {
                {"intance", null },
            };

            await _NavigationService.NavigateAsync("ScanURNPage", parameters).ConfigureAwait(false);
        }
        #endregion
    }
}
