using inutralia.Models;
using MvvmHelpers;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Xamarin.Forms;

namespace inutralia.ViewModels.QuestionsSpecialist
{
    public class NewQuestionViewModel : BaseNavigationViewModel
    {
        public enum Estatus
        {
            Pending,
            Answered_for_client,
            Answered_for_nutricionist,
            Closed
        }

        public QuestionSpecialist QuestionSpecialist { private set; get; }

        public Estatus State => (Estatus)QuestionSpecialist?.Id;

        public ObservableRangeCollection<QuestionMessage> _NewQuestion;

        // Comando de update del listado
        Command _RefreshNewQuestionCommand;

        // Comando de borrado de elemento
        Command _DeleteNewQuestionCommand;

        public NewQuestionViewModel(QuestionSpecialist quest)
        {
            QuestionSpecialist = quest;

            Title = QuestionSpecialist.Subject;

            if (quest.Messages.Count() > 0)
            {
                NewQuestion = new ObservableRangeCollection<QuestionMessage>(quest.Messages);
            }

            else
            {
                NewQuestion = new ObservableRangeCollection<QuestionMessage>();
            }
        }

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

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

        public async Task RefreshData()
        {
            if (QuestionSpecialist == null || (QuestionSpecialist.Id < 0))
                return;

            IsBusy = true;

            if (await App.API.RefreshItemAsync(QuestionSpecialist))
            {
                Title = QuestionSpecialist.StatusImg;
                OnPropertyChanged("Status");
            }

            IsBusy = false;

            await FetchQuestions();
        }

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

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

        /// <summary>
        /// Proceso de ejecución del comando de actualización del listado
        /// </summary>
        async Task ExecuteRefreshQuestionMessagesCommand()
        {
            try
            {
                // Hace que el comando no se pueda ejecutar de nuevo
                RefreshNewQuestionCommand.ChangeCanExecute();
                // Realiza el proceso de actualización
                await FetchQuestions();
                // Hace que el comando pueda volver a ejecutarse
                RefreshNewQuestionCommand.ChangeCanExecute();
            }
            catch (System.Exception e)
            {
                string err = e.Message;
            }
        }

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

            // Llamada al API para coger el listado (provoca que se actualize la vista del listado)
            try
            {
                if (await App.API.RefreshItemAsync(QuestionSpecialist) == true)
                {
                    Title = QuestionSpecialist.Subject;
                    NewQuestion = new ObservableRangeCollection<QuestionMessage>(QuestionSpecialist.Messages);
                }
            }

            catch (System.Exception e)
            {
                string err = e.Message;
                NewQuestion.Clear();
            }
        }

        ///<summary>
        ///Acceso al comando de borrado de pregunta
        ///</summary>
        public Command DeleteQuestionCommand
        {
            // 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 _DeleteNewQuestionCommand ?? (_DeleteNewQuestionCommand = new Command(async (parameter) => await ExecuteDeleteQuestionCommand(parameter as QuestionMessage)));
            }
        }

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

                // Llamamos al API para borrar el mensaje
                await App.API.DeleteItemAsync(messag);

                //Actualizamos la lista
                await FetchQuestions();

                //Indicamos que no estámos ocupados (provoca que desarparezca el indicador de carga)
                IsBusy = false;
            }
        }

        ///<summary>
        ///Guarda un mensaje perteneciente a QuestionSpecialist ya sea una pregunta nueva, nuevo mensaje o edición
        ///</summary>
        ///<param name="text"></param>
        ///<returns></returns>
        public async Task SaveQuestion(string text)
        {
            var q = QuestionSpecialist;
            HttpMethod method = HttpMethod.Post;

            IsBusy = true;

            if (q.Id < 0)
            {
                var data = new Dictionary<string, string>()
                {
                    {"subject", q.Subject }, {"message", text}
                };
                // New Question
                await App.API.RawMessage(method, string.Format("questions"), data, q);
            }
            else
            {
                QuestionMessage msg;
                if (q.State == QuestionSpecialist.Estatus.Pending)
                {
                    //Edit last Message
                    msg = q.Messages.Last();
                    method = HttpMethod.Put;
                }
                else
                {
                    //Add new Message
                    msg = new QuestionMessage();
                } //endif

                msg.Text = text;

                await App.API.RawMessage(method, string.Format("questions/{0}", q.Id), msg, q);
            } // endif

            IsBusy = false;

            NewQuestion = new ObservableRangeCollection<QuestionMessage>(QuestionSpecialist.Messages);
        }

        ///<summary>
        ///Actualiza una pregunta
        ///</summary>
        ///<returns></returns>
        public async Task SaveQuestion()
        {
            var q = QuestionSpecialist;
            HttpMethod method = HttpMethod.Post;

            IsBusy = true;

            await App.API.UpdateItemAsync(q);

            if (await App.API.RefreshItemAsync(QuestionSpecialist))
            {
                Title = QuestionSpecialist.StatusImg;
                OnPropertyChanged("State");
            }

            IsBusy = false;
        }

        public bool IsCloseOrPending => (State == Estatus.Answered_for_client || State == Estatus.Answered_for_nutricionist || State == Estatus.Pending || State == Estatus.Closed) && QuestionSpecialist.Messages.Count() > 0 || State == Estatus.Answered_for_nutricionist;

        public bool MayBeClosed => !IsCloseOrPending;
    }
}
