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

    /// <summary>
    /// ViewModel de un menú semanal
    /// </summary>

    public abstract class MenuBaseViewModel : ModelBasedViewModel
    {
        public MenuBaseViewModel(MenuBase menu) : base(menu)
        {
            Title = WeekMenu?.Title;
        }

        #region Properties

        /// <summary>
        /// El menú semanal mostrado
        /// </summary>
        public virtual MenuBase WeekMenu => Model as MenuBase;

        /// <summary>
        /// Backup variable para el índice del día seleccionado
        /// </summary>
        protected int _Index = -1;

        /// <summary>
        /// Índice del día seleccionado
        /// </summary>
        public int Index
        {
            get { return _Index; }
            set
            {
                if ((_Index != value) && (value >= 0) && (value < WeekMenu?.Days?.Count))
                {
                    _Index = value;
                    OnPropertyChanged("Index");
                    OnPropertyChanged("CurrentDay");

                    OnIndexChanged();
                } //endif
            }
        }

        /// <summary>
        /// Retorna el día seleccionado
        /// </summary>
        public Day CurrentDay
        {
            get
            {
                return ((Index >= 0) && (Index < WeekMenu?.Days?.Count)) ? WeekMenu.Days[Index] : null;
            }
        }

        protected bool _LoadingRecipes = false;

        /// <summary>
        /// Indica si se están cargando recetas
        /// </summary>
        public bool IsLoadingRecipes
        {
            get { return _LoadingRecipes; }
            set
            {
                SetProperty(ref _LoadingRecipes, value, "IsLoadingRecipes");
                OnPropertyChanged("IsNotLoadingRecipes");
            }
        }

        /// <summary>
        /// Indica si no se están cargando recetas
        /// </summary>
        public bool IsNotLoadingRecipes
        {
            get { return !_LoadingRecipes; }
            set
            {
                SetProperty(ref _LoadingRecipes, !value, "IsLoadingRecipes");
                OnPropertyChanged("IsNotLoadingRecipes");
            }
        }

        #endregion

        #region Commands

        protected Command _ShowRecipeCommand = null;

        /// <summary>
        /// Comando para mostrar una receta
        /// </summary>
        public Command ShowRecipeCommand => _ShowRecipeCommand ??
            (_ShowRecipeCommand = new Command(async (parameter) => await ShowRecipe(parameter as Recipe)));

        protected Command _ShowRecomendationCommand = null;

        /// <summary>
        /// Comando para mostrar las recomendaciones
        /// </summary>
        public Command ShowRecomendationCommand => _ShowRecomendationCommand ??
            (_ShowRecomendationCommand = new Command(async () => await ShowRecomendation()));

        #endregion

        #region Tasks

        /// <summary>
        /// Actualiza los datos de todas las recetas
        /// </summary>
        public async Task LoadAllRecipesAsync()
        {
            IsLoadingRecipes = true;

            // Obtener las recetas completas
            foreach (var d in WeekMenu.Days)
            {
                foreach (var r in d.LunchFirst)
                    await App.API.RefreshItemAsync(r);
                foreach (var r in d.LunchSecond)
                    await App.API.RefreshItemAsync(r);
                foreach (var r in d.DinnerFirst)
                    await App.API.RefreshItemAsync(r);
                foreach (var r in d.DinnerSecond)
                    await App.API.RefreshItemAsync(r);
            } //endforeach

            IsLoadingRecipes = false;
        }

        /// <summary>
        /// Navega a la vista de receta
        /// </summary>
        /// <param name="recipe">La receta a mostrar</param>
        protected async Task ShowRecipe(Recipe recipe)
        {
            await PushAsync(new RecipeDetailView() { BindingContext = new RecipeViewModel(recipe) });
        }

        /// <summary>
        /// Navega a la vista de recomendaciones
        /// </summary>
        protected async Task ShowRecomendation()
        {
            await PushAsync(new RecomendationView() { BindingContext = WeekMenu });
        }

        #endregion

        /// <summary>
        /// Llamado cuando se han actualizado los datos
        /// </summary>
        protected override void OnDataRefreshed()
        {
            base.OnDataRefreshed();

            // Informar que ha cambiado el menú
            OnPropertyChanged("WeekMenu");

            // Cambiar título
            Title = WeekMenu?.Title;

            // Si no tenemos un día seleccionado, seleccionar automáticamente 
            // el día de la semana en el que estemos
            if (Index < 0)
            {
                DayOfWeek dw = DateTime.Now.DayOfWeek;

                // Como DayOfWeek empieza con el 0 en Domingo, le "restamos 1 modulo 7"
                Index = ((int)dw + 6) % 7;
            } //endif

            // Informar que ha cambiado el día actual (aunque no cambie el índice 
            // puede haber cambiado el contenido)
            OnPropertyChanged("CurrentDay");
        }

        /// <summary>
        /// Llamado cuando ha cambiado el índice del día seleccionado
        /// </summary>
        protected virtual void OnIndexChanged() { }
    }
}
