using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.ServiceModel.DomainServices.Client;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using TaskIt.Assets.Resources;
using TaskIt.Core;
using TaskIt.Infrastructure;
using TaskIt.Modules.Dashboard.Assets.Resources;
using TaskIt.ViewModels;
using TaskIt.Web;
using TaskIt.Web.Services;
using Telerik.Windows.Controls.Scheduler;

namespace TaskIt.Modules.Dashboard.ViewModels
{
    [Export]
    public class TasksDueThisWeekViewModel : WidgetViewModelBase
    {
        readonly DataContext _dataContext = new DataContext();
        private Appointment _selectedCalendarItem;
        private Task _selectedItem;

        public TasksDueThisWeekViewModel()
        {
            LoadData();
            Messenger.Default.Register<ModuleEnum>(this, OnPageEnter);
            Messenger.Default.Register<EntityDeletionCompletedArgs>(this, OnItemDeleted);
        }

        private void OnPageEnter(ModuleEnum args)
        {
            if (args == ModuleEnum.Dashboard)
            {
                LoadData();
            }
        }

        private void LoadData()
        {
            ShowBusyIndicator(); 
            DataProvider.GetTasksDueThisWeek(_dataContext, Utils.CurrentUserID, OnTasksDueThisWeekLoaded);
        }

        // TODO: Ross - Haven't implemented page to page navigation yet
        //public override void OnEdit()
        //{    
        //    Messenger.Default.Send(ModuleEnum.Tasks);     
        //    base.OnEdit();
        //}

        void OnTasksDueThisWeekLoaded(LoadOperation<Task> lo)
        {
            if (lo.HasError)
            {
                Utils.ShowErrorMessage(DashboardErrorStrings.Message_LoadingTasksDueThisWeekFailed, lo.Error.Message);                
                lo.MarkErrorAsHandled();
                return;
            }

            TasksDueThisWeek = lo.Entities;
            UpdateCalendarItems();
            HideBusyIndicator();
        }

        private void LoadCalendarItems()
        {
            CalendarItems = new DefaultAppointmentCollection();
            foreach (var item in TasksDueThisWeek)
            {
                CalendarItems.Add(new Appointment { UniqueId = item.ID.ToString(), Category = Utils.GetAppointmentCategory(item.TaskCategoryID), Subject = item.Name, Start = (DateTime)item.DueDate, End = (DateTime)item.DueDate });
            }
        }

        public void OnItemDeleted(EntityDeletionCompletedArgs args)
        {
            UpdateCalendarItems();
        }

        public void OnMarkCompleted()
        {
            SelectedItem.CompletionDate = DateTime.Now;
            Utils.ShowBusyIndicator();
            _dataContext.SubmitChanges(OnSubmitCompleted, null);
        }

        public override void OnSubmitCompleted(SubmitOperation so)
        {
            Utils.HideBusyIndicator();
            if (so.HasError)
            {
                Utils.ShowErrorMessage(ErrorStrings.Message_SubmitFailed, so.Error.Message);
                so.MarkErrorAsHandled();
                return;
            }
            
            _dataContext.RejectChanges();
            UpdateCalendarItems();
        }

        private void UpdateCalendarItems()
        {
            LoadCalendarItems();
            this.OnPropertyChanged(p => p.CalendarItems);
        }

        # region Properties

        private IEnumerable<Task> TasksDueThisWeek { get; set; }

        public DefaultAppointmentCollection CalendarItems { get; set; }

        public Appointment SelectedCalendarItem
        {
            get { return _selectedCalendarItem; }
            set
            {
                _selectedCalendarItem = value; 
                this.OnPropertyChanged(p => p.SelectedCalendarItem);
                try
                {
                    SelectedItem = TasksDueThisWeek.Where(t => t.ID == Convert.ToInt32(value.UniqueId)).First();
                }
                catch (Exception)
                {
                    SelectedItem = null;
                }                
            }
        }

        public Task SelectedItem
        {
            get { return _selectedItem; }
            set { _selectedItem = value; this.OnPropertyChanged(p => p.SelectedItem); }
        }

        # endregion

        # region Commands

        private RelayCommand _markCompletedCommand;
        public RelayCommand MarkCompletedCommand
        {
            get { return _markCompletedCommand ?? (_markCompletedCommand = new RelayCommand(OnMarkCompleted)); }
        }

        # endregion

    }
}
