namespace inutralia.ViewModels
{
    using inutralia.Models;
    using MvvmHelpers;
    using System.Collections.Generic;
    using System.Net.Http;
    using System.Threading.Tasks;
    using Xamarin.Forms;

    public class RecipeListViewModel : BaseNavigationViewModel
    {
        public RecipeListViewModel()
        {
            Title = "Recetas";
            Filters = new RecipeListOptionsViewModel();
        }

        public RecipeListOptionsViewModel Filters { get; private set; }

        // Lista de articulos
        ObservableRangeCollection<Recipe> _Recipes;

        // Comando de update del listadd
        Command _RefreshRecipesCommand;

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

            // Setter. cambiar el valor y notifica a la vista de dicho cambio
            set
            {
                _Recipes = value;
                OnPropertyChanged("Recipes");
            }
        }

        // Indica si hay resultados
        public bool IsEmpty => IsNotBusy && (Recipes.Count < 1);
        public bool IsNotEmpty => IsNotBusy && (Recipes.Count > 0);

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

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


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

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

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

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

            // Llamada al API 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
            {
                string flags = string.Empty;
                string orFlags = string.Empty;
                foreach (var gr in Filters.Groups)
                {
                    foreach (var cat in gr.Group.Options)
                    {
                        if (cat.Selected)
                        {
                            if (gr.Group.Id == 1)
                            {
                                if (orFlags.Length > 0)
                                    orFlags += ",";
                                orFlags += cat.Id.ToString();
                            }
                            else
                            {
                                if (flags.Length > 0)
                                    flags += ",";
                                flags += cat.Id.ToString();
                            } //endif
                        } //endif
                    } //endforeach
                } //endforeach

                if (string.IsNullOrEmpty(flags) && string.IsNullOrEmpty(orFlags) && string.IsNullOrEmpty(Filters?.Desc))
                {
                    Recipes = new ObservableRangeCollection<Recipe>(await App.API.RefreshListAsync<Recipe>());
                }
                else
                {
                    var options = new Dictionary<string, string>();
                    if (!string.IsNullOrEmpty(flags)) options.Add("flags", flags);
                    if (!string.IsNullOrEmpty(orFlags)) options.Add("flags_or", orFlags);
                    if (!string.IsNullOrEmpty(Filters?.Desc)) options.Add("desc", Filters.Desc);

                    var recipes = await App.API.RawMessage<List<Recipe>>(HttpMethod.Post, "recipes", options);
                    Recipes = new ObservableRangeCollection<Recipe>(recipes);
                } //endif
            }
            catch (System.Exception e)
            {
                Recipes.Clear();
            }

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