namespace inutralia.ViewModels
{
    using inutralia.Models;
    using MvvmHelpers;
    using System.Threading.Tasks;
    using Xamarin.Forms;

    public class ShoppingListViewModel : BaseNavigationViewModel
    {
        public ShoppingListViewModel() { }

        ObservableRangeCollection<ShoppingList> _ShoppingList;

        // Comando de update del listado
        Command _RefreshShoppingListCommand;

        // Comando de borrado de elemento
        Command _DeleteShoppingListCommand;

        // Acceso a la lista de ingredientes
        public ObservableRangeCollection<ShoppingList> ShoppingList
        {
            // Getter (lazy load), crea la lista si no existe
            get { return _ShoppingList ?? (_ShoppingList = new ObservableRangeCollection<ShoppingList>()); }

            // Setter. Cambia el valor y notifica a la vista de dicho cambio
            set
            {
                _ShoppingList = value;
                OnPropertyChanged("ShoppingList");
            }
        }

        public async Task AddItem(ShoppingList item)
        {
            // Añadir elemento y refrescar lista
            if (await App.LocalData.UpdateItemAsync(item, true) != null)
                await FetchShoppingList();
        }

        public async Task DeleteSelected()
        {
            IsBusy = true;

            foreach (var item in ShoppingList)
                if (item.Select)
                    await App.LocalData.DeleteItemAsync(item);

            ShoppingList.Clear();

            await FetchShoppingList();
        }

        public async Task DeleteAll()
        {
            IsBusy = true;

            foreach (var item in ShoppingList)
                await App.LocalData.DeleteItemAsync(item);

            ShoppingList.Clear();

            await FetchShoppingList();
        }

        /// <summary>
        /// Método que realiza la carga inicial del listado
        /// </summary>
        public async Task ExecuteLoadShoppingListCommand()
        {
            // Realiza el proceso de actualización si hay menos de un 
            // elemento en el listado
            if (ShoppingList.Count < 1)
                await FetchShoppingList();
        }

        /// <summary>
        /// Acceso al comando de actualización del listado
        /// </summary>
        public Command RefreshShoppingListCommand
        {
            // Getter (lazy load), crea el comando si no existe
            get { return _RefreshShoppingListCommand ?? (_RefreshShoppingListCommand = new Command(async () => await ExecuteRefreshShoppingListCommand())); }
        }


        /// <summary>
        /// Proceso de ejecución del comando de actualización del listado
        /// </summary>
        async Task ExecuteRefreshShoppingListCommand()
        {
            // Hace que el comando no se pueda ejecutar de nuevo
            RefreshShoppingListCommand.ChangeCanExecute();

            // Realiza el proceso de actualización
            await FetchShoppingList();

            // Hace que el comando pueda volver a ejecutarse
            RefreshShoppingListCommand.ChangeCanExecute();
        }

        /// <summary>
        /// Proceso de actualización del listado
        /// </summary>
        async Task FetchShoppingList()
        {
            // Indicamos que estamos ocupados (provoca que aparezca el indicador de carga)
            IsBusy = true;

            // Llamada a LocalData para coger el listado (provoca que se actualize la vista del listado)
            // Nota: Al obtener el listado, el controlador Rest del servidor no retorna el cuerpo de
            // la notificación (campo Body)

            try
            {
                // Obtener lista
                var list = await App.LocalData.RefreshListAsync<ShoppingList>();

                // Ordenarla
                list.Sort((a, b) => { return a.Text.CompareTo(b.Text); });

                // Asignarla a la que utiliza la vista
                ShoppingList = new ObservableRangeCollection<ShoppingList>(list);
            }
            catch (System.Exception)
            {
                ShoppingList.Clear();
            }

            // Indicamos que ya no estamos ocupados (provoca que desaparezca el indicador de carga)
            IsBusy = false;
        }

        public Command DeleteShoppingListCommand
        {
            // Getter (lazy load), crea el comando si no existe. Nótese que, a diferencia del comando
            // de Refresh, éste recibe una notificación como parámetro
            get
            {
                return _DeleteShoppingListCommand ??
                    (_DeleteShoppingListCommand = new Command(async (parameter) => await ExecuteDeleteShoppingListCommand(parameter as ShoppingList)));
            }
        }

        /// <summary>
        /// Proceso de ejecución de comando de borrado
        /// </summary>
        /// <param name="shoplist"></param>
        /// <returns></returns>
        /// 
        async Task ExecuteDeleteShoppingListCommand(ShoppingList shoplist)
        {
            // Verificar parámetro
            if (shoplist != null)
            {
                // Indicamos que estamos ocupados (provoca que aparezca el indicador de carga)
                IsBusy = true;

                // Llamamos a LocalData para borrar la notificación
                await App.LocalData.DeleteItemAsync(shoplist);

                // Actualizamos la lista
                await FetchShoppingList();

                // Indicamos que ya no estamos ocupados 
                IsBusy = false;
            } //endif
        }
    }
}
