using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel.Composition;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Net.NetworkInformation;
using System.ServiceModel.DomainServices.Client;
using System.Windows;
using System.Windows.Controls;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using TaskIt.Assets.Resources;
using TaskIt.Core;
using TaskIt.Infrastructure;
using TaskIt.Modules.Tasks.Assets.Resources;
using TaskIt.Modules.Tasks.Core;
using TaskIt.Modules.Tasks.Models;
using TaskIt.Web;
using Telerik.Windows.Controls;
using Telerik.Windows.Controls.DragDrop;
using Telerik.Windows.Controls.GridView;
using Telerik.Windows.Controls.Scheduler;

namespace TaskIt.Modules.Tasks.ViewModels
{
    [Export]
    public class ListViewModel : TasksViewModelBase
    {
        private Task _selectedItem;
        private ObservableCollection<Task> _selectedItems;
        private Appointment _selectedCalendarItem;
        private EntityFilterArgs _selectedEntityFilterArgs;
        private TaskView _selectedTaskView = TaskView.Grid;
        private TaskStatus _selectedTaskStatus;
        private TaskCategory _selectedTaskCategory;
        private TaskNote _selectedNote;
        private CategoryCollection _calendarCategories;
        private List<TaskStatus> _taskStatuses;
        private bool _isGridView;
        private bool _isCalendarView;
        private bool _hasTasks = true;

        public ListViewModel()
        {
            IsGridView = true;

            Messenger.Default.Register<TaskUpdateCompletedArgs>(this, OnTasksUpdated);
            Messenger.Default.Register<EntityFilterArgs>(this, OnFilterByRelation);
            Messenger.Default.Register<NewEntityArgs>(this, OnNewItem);
            Messenger.Default.Register<SaveEntityArgs>(this, OnSaveItem);
            Messenger.Default.Register<DetailsViewCompletedArgs>(this, OnDetailsViewCompleted);
            Messenger.Default.Register<DetailsViewCanceledArgs>(this, OnDetailsViewCanceled);
            Messenger.Default.Register<NoteSaveCompletedArgs>(this, OnNoteSaveCompleted);  
        }

        public void LoadTasks()
        {
            Utils.ShowBusyIndicator();
            Utils.DataContext.Tasks.Clear();

            var isCalendarView = SelectedTaskView == TaskView.Calendar;
            switch (SelectedEntityFilterArgs.EntityType)
            {
                case EntityType.TaskCategory:
                    if (SelectedEntityFilterArgs.ID == 0) // All categories
                    {
                        // TODO: Ross - Not sure about this
                        SelectedTaskCategory = null;
                        DataProvider.GetAllTasks(Utils.CurrentUserID, SelectedTaskStatus.Value, isCalendarView, OnTasksLoaded);
                    }
                    else
                    {
                        SelectedTaskCategory = TaskCategories.Where(c => c.ID == SelectedEntityFilterArgs.ID).First();
                        DataProvider.GetTasksByCategory(Utils.CurrentUserID, SelectedEntityFilterArgs.ID, SelectedTaskStatus.Value, isCalendarView, OnTasksLoaded);                                   
                    }
                    break;
                case EntityType.Project:
                    SelectedProject = Projects.Where(c => c.ID == SelectedEntityFilterArgs.ID).First();
                    DataProvider.GetTasksByProject(Utils.CurrentUserID, SelectedEntityFilterArgs.ID, SelectedTaskStatus.Value, isCalendarView, OnTasksLoaded);
                    break;
                case EntityType.Context:
                    SelectedContext = Contexts.Where(c => c.ID == SelectedEntityFilterArgs.ID).First();
                    DataProvider.GetTasksByContext(Utils.CurrentUserID, SelectedEntityFilterArgs.ID, SelectedTaskStatus.Value, isCalendarView, OnTasksLoaded);
                    break;
                default:
                    SelectedContact = Contacts.Where(c => c.ID == SelectedEntityFilterArgs.ID).First();
                    DataProvider.GetTasksByContact(Utils.CurrentUserID, SelectedEntityFilterArgs.ID, SelectedTaskStatus.Value, isCalendarView, OnTasksLoaded);
                    break;
            }
        }

        public void OnNew(EntityType entityType)
        {
            Mode = ItemMode.Add;
            Messenger.Default.Send(new NewEntityArgs(entityType));
            Messenger.Default.Send(new ViewEntityFormArgs(entityType));
        }

        public void OnEdit()
        {
            Mode = ItemMode.Edit;
            OnLoadNotes();
            var entityType = EntityType.Task; // TODO: Ross - This is temporary...the New button will eventually support adding more than just Tasks
            Messenger.Default.Send(new EditEntityArgs(entityType, SelectedItem.ID));
            Messenger.Default.Send(new ViewEntityFormArgs(entityType));
        }

        public override void OnLoadNotes()
        {
            base.OnLoadNotes();
            DataProvider.GetTaskNotes(SelectedItem.ID, OnTaskNotesLoaded);
        }

        protected void OnNewItem(NewEntityArgs args)
        {
            if (IsTask(args))
            {
                SelectedItem = new Task
                   {
                       Name = CommonStrings.Watermark_Name,
                       UserID = Utils.CurrentUserID,
                       TaskCategory = SelectedTaskCategory,
                       Project = SelectedProject,
                       Context = SelectedContext,
                       Contact = SelectedContact,
                       Priority = Utils.DataContext.Priorities.First(),
                       CreatedDate = DateTime.Now // This will be reset on the server, but we need to set it to something to prevent an error when submitting
                   };
            }

            if (IsTaskNote(args))
            {
                SelectedNote = new TaskNote
                {
                    Text = CommonStrings.Watermark_Name,
                    UserID = Utils.CurrentUserID,
                    TaskID = SelectedItem.ID,
                    CreatedDate = DateTime.Now // This will be reset on the server, but we need to set it to something to prevent an error when submitting
                };
            }
        }

        protected void OnSaveItem(SaveEntityArgs args)
        {
            if (IsTask(args) && Mode == ItemMode.Add)
            {
                Utils.DataContext.Tasks.Add(SelectedItem);
            }
            else if (IsTaskNote(args))
            {
                Utils.DataContext.TaskNotes.Add(SelectedNote);
            }
        }

        public void OnTasksUpdated(object obj)
        {
            this.OnPropertyChanged(p => p.Tasks);
            this.OnPropertyChanged(p => p.CalendarTasks);
        }

        public void OnFilterByRelation(EntityFilterArgs args)
        {
            SelectedEntityFilterArgs = args;
            IsInitialized = false;
            InitializeSelections();
            LoadTasks();

            this.OnPropertyChanged(p => p.IsMoveToCommandAvailable);
            this.OnPropertyChanged(p => p.IsMoveToInboxCommandAvailable);
            this.OnPropertyChanged(p => p.IsMoveToActionsCommandAvailable);
            this.OnPropertyChanged(p => p.IsMoveToWaitingCommandAvailable);
            this.OnPropertyChanged(p => p.IsMoveToSomedayCommandAvailable);
            this.OnPropertyChanged(p => p.IsMoveToTicklersCommandAvailable);
            this.OnPropertyChanged(p => p.IsMoveToReferenceCommandAvailable);
            this.OnPropertyChanged(p => p.IsSendToCommandAvailable);
            this.OnPropertyChanged(p => p.IsNotFilteredByProject);
            this.OnPropertyChanged(p => p.IsNotFilteredByContext);
            this.OnPropertyChanged(p => p.IsNotFilteredByContact);
            this.OnPropertyChanged(p => p.IsNotFilteredByCategory);
        }

        private void InitializeSelections()
        {
            SelectedTaskStatus = TaskStatuses.First();
            SelectedTaskCategory = TaskCategories.First();
            SelectedProject = Projects.First();
            SelectedContext = Contexts.First();
            SelectedContact = Contacts.First();
            IsInitialized = true;
        }

        public void OnDetailsViewCompleted(DetailsViewCompletedArgs obj)
        {
            this.OnPropertyChanged(p => p.Tasks);
            this.OnPropertyChanged(p => p.CalendarTasks);
            Messenger.Default.Send(new ViewListArgs());
        }

        public void OnDetailsViewCanceled(DetailsViewCanceledArgs obj)
        {
            Messenger.Default.Send(new ViewListArgs());
        }

        protected void OnNoteSaveCompleted(NoteSaveCompletedArgs args)
        {
            if (!IsTaskNote(args))
            {
                return;
            }
            HasNotes = true;
            this.OnPropertyChanged(p => p.Notes);
        }

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

        public void OnSendToTwitter()
        {
            var currentUser = Utils.CurrentUser;
            var username = currentUser.TwitterUsername;
            var password = currentUser.TwitterPassword;

            if (username == null || password == null || Utils.IsStringEmpty(username) || Utils.IsStringEmpty(password))
            {
                Messenger.Default.Send(new ErrorArgs(ErrorStrings.Message_TwitterCredentialsNotSet));
                return;
            }

            TweetMessage = GetDefaultTweetMessage();
            this.OnPropertyChanged(m => m.TweetMessage);
            NotifyTwitterMessage();
        }

        public void OnExecuteSendToTwitter()
        {
            if (!NetworkInterface.GetIsNetworkAvailable())
            {
                // TODO: Ross - This functionality is not complete
                HandleOfflineTweet(TweetMessage);
                return;
            }

            var currentUser = Utils.CurrentUser;
            var username = currentUser.TwitterUsername;
            var password = currentUser.TwitterPassword;
            Utils.DataContext.Tweet(username, password, TweetMessage, OnTweetCompleted, null);
        }

        public void OnCloseTwitterWindow()
        {
            NotifyCloseTwitterWindow();
        }

        public void OnSendToFacebook()
        {
            MessageBox.Show("This feature is not currently implemented");
        }

        private string GetDefaultTweetMessage()
        {
            var message = Constants.TWITTER_HASH_MESSAGE + " " + SelectedItem.Name;
            return message.Length <= 115 ? message : message.Substring(0, 115);
        }

        private static void HandleOfflineTweet(string message)
        {
            Utils.HideBusyIndicator();
            if (IsolatedStorageManager.ExistsInIsolatedStorage(Constants.TWEET_STORAGE))
            {
                MessageBox.Show("Network connection is not available and only 1 tweet can be stored for delayed posting to Twitter.");
            }
            else
            {
                IsolatedStorageSettings.ApplicationSettings.Add(Constants.TWEET_STORAGE, message);
                MessageBox.Show("Network connection is not available. The post will be stored until connectivity returns.");
            }
        }

        public virtual void OnTweetCompleted(InvokeOperation so)
        {
            OnCloseTwitterWindow();
            Utils.HideBusyIndicator();
            if (!so.HasError)
            {
                return;
            }
            var errorMessage = so.Error.Message.IndexOf("(401) Unauthorized") > -1 ? TasksErrorStrings.Message_TwitterCredentialsFailed : so.Error.Message;
            Utils.ShowErrorMessage(ErrorStrings.Message_SubmitFailed, errorMessage);
            so.MarkErrorAsHandled();
        }

        public void OnMoveTo(TaskCategoryEnum taskCategoryEnum)
        {
            Utils.ShowBusyIndicator();
            SelectedItem.TaskCategoryID = Convert.ToInt32(taskCategoryEnum);
            Utils.DataContext.SubmitChanges(OnSubmitCompleted, null);
        }

        public void OnViewGrid()
        {
            SelectedTaskView = TaskView.Grid;
            NotifyViewGrid();
        }

        public void OnViewCalendar()
        {
            SelectedTaskView = TaskView.Calendar;
            NotifyViewCalendar();
        }

        public Task SelectedItem
        {
            get { return _selectedItem; }
            set
            {
                _selectedItem = value;
                Utils.DataContext.TaskNotes.Clear(); // TODO: Ross - Not sure if this is the appropriate place
                this.OnPropertyChanged(p => p.SelectedItem);
                this.OnPropertyChanged(p => p.SelectedCalendarItem);
            }
        }

        private static bool IsTask(EntityArgs args)
        {
            return args.EntityType == EntityType.Task;
        }

        private static bool IsTaskNote(EntityArgs args)
        {
            return args.EntityType == EntityType.TaskNote;
        }

        public ObservableCollection<Task> SelectedItems
        {
            get { return _selectedItems; }
            set { _selectedItems = value; this.OnPropertyChanged(p => p.SelectedItems); }
        }

        public Appointment SelectedCalendarItem
        {
            get { return _selectedCalendarItem; }
            set
            {
                _selectedCalendarItem = value;
                this.OnPropertyChanged(p => p.SelectedCalendarItem);
                SelectedItem = (value == null) ? null : GetSelectedCalendarTask(value.UniqueId);
            }
        }

        public Task GetSelectedCalendarTask(string uniqueID)
        {
            return Tasks.Where(t => t.ID == Convert.ToInt32(uniqueID)).First();
        }

        public EntityFilterArgs SelectedEntityFilterArgs
        {
            get { return _selectedEntityFilterArgs; }
            set { _selectedEntityFilterArgs = value; this.OnPropertyChanged(p => p.SelectedEntityFilterArgs); }
        }

        public IEnumerable<Task> Tasks
        {
            get
            {
                if (SelectedEntityFilterArgs == null)
                {
                    return Utils.DataContext.Tasks;
                }

                // NOTE: We need this filtering in case a task is moved to a different category via the Move To command, or is marked as completed
                switch (SelectedEntityFilterArgs.EntityType)
                {
                    case EntityType.TaskCategory:
                        return SelectedTaskCategory == null ?
                            Utils.DataContext.Tasks.Where(t => t.IsComplete == SelectedTaskStatus.Value) :
                            Utils.DataContext.Tasks.Where(t => t.TaskCategoryID == SelectedTaskCategory.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value);
                    case EntityType.Project:
                        return Utils.DataContext.Tasks.Where(t => t.ProjectID == SelectedProject.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value);
                    case EntityType.Context:
                        return Utils.DataContext.Tasks.Where(t => t.ContextID == SelectedContext.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value);
                    default:
                        return Utils.DataContext.Tasks.Where(t => t.ContactID == SelectedContact.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value);
                }
            }
        }

        public IOrderedEnumerable<TaskNote> Notes
        {
            get { return Utils.DataContext.TaskNotes.OrderByDescending(n => n.CreatedDate); }
        }

        public List<TaskStatus> TaskStatuses
        {
            get { return _taskStatuses ?? (_taskStatuses = TaskStatus.GetTaskStatuses()); }
        }

        public EntityType EntityType
        {
            get { return EntityType.Task; }
        }

        public EntityType NoteEntityType
        {
            get { return EntityType.TaskNote; }
        }

        public DefaultAppointmentCollection CalendarTasks
        {
            get
            {
                IEnumerable<Task> tasks;
                if (SelectedEntityFilterArgs == null)
                {
                    tasks = Utils.DataContext.Tasks;
                }
                else
                {
                    // NOTE: We need this filtering in case a task is moved to a different category via the Move To command, or is marked as completed
                    switch (SelectedEntityFilterArgs.EntityType)
                    {
                        case EntityType.TaskCategory:
                            tasks = (SelectedTaskCategory == null) ?
                                Utils.DataContext.Tasks.Where(t => t.IsComplete == SelectedTaskStatus.Value).Where(t => t.DueDate != null) :
                                Utils.DataContext.Tasks.Where(t => t.TaskCategoryID == SelectedTaskCategory.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value).Where(t => t.DueDate != null);
                            break;
                        case EntityType.Project:
                            tasks = Utils.DataContext.Tasks.Where(t => t.ProjectID == SelectedProject.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value).Where(t => t.DueDate != null);
                            break;
                        case EntityType.Context:
                            tasks = Utils.DataContext.Tasks.Where(t => t.ContextID == SelectedContext.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value).Where(t => t.DueDate != null);
                            break;
                        default:
                            tasks = Utils.DataContext.Tasks.Where(t => t.ContactID == SelectedContact.ID).Where(t => t.IsComplete == SelectedTaskStatus.Value).Where(t => t.DueDate != null);
                            break;
                    }
                }

                // TODO: Ross - If a new task is added w/ a null DueDate, it will break when the Calendar is rebound

                var appointments = new DefaultAppointmentCollection();
                foreach (var task in tasks)
                {
                    appointments.Add(new Appointment { UniqueId = task.ID.ToString(), Category = Utils.GetAppointmentCategory(task.TaskCategoryID), Subject = task.Name, Start = (DateTime)task.DueDate, End = (DateTime)task.DueDate });
                }
                return appointments;
            }
        }

        public CategoryCollection CalendarCategories
        {
            get { return _calendarCategories ?? (_calendarCategories = CalendarCategory.GetCategories()); }
        }

        public TaskStatus SelectedTaskStatus
        {
            get { return _selectedTaskStatus; }
            set
            {
                _selectedTaskStatus = value;
                if (IsInitialized)
                {
                    LoadTasks();
                }
                this.OnPropertyChanged(m => m.SelectedTaskStatus);
            }
        }

        public TaskView SelectedTaskView
        {
            get { return _selectedTaskView; }
            set
            {
                _selectedTaskView = value;
                // TODO: Ross - Not sure why this was here...remove it unless there is a need to bring it back
                // It was causing data to be reloaded when moving from Grid to Calendar view
                //LoadTasks();
            }
        }

        public TaskCategory SelectedTaskCategory
        {
            get { return _selectedTaskCategory; }
            set { _selectedTaskCategory = value; this.OnPropertyChanged(p => p.SelectedTaskCategory); }
        }

        public TaskNote SelectedNote
        {
            get { return _selectedNote; }
            set { _selectedNote = value; this.OnPropertyChanged(p => p.SelectedNote); }
        }

        public string TweetMessage { get; set; }

        public void HandleGridTaskDrag(DragDropQueryEventArgs e)
        {
            if (e.OriginalSource is GridViewHeaderCell || SelectedItem == null)
            {
                return;
            }

            var tasks = new List<object> { SelectedItem };
            var payload = new DragDropViewModel { DraggedItems = tasks, Message = SelectedItem.Name };
            e.Options.Payload = payload;

            e.Handled = true;
            e.QueryResult = true;
        }

        public void HandleCalendarTaskDrag(DragDropQueryEventArgs e)
        {
            if (SelectedCalendarItem == null)
            {
                return;
            }
            var task = GetSelectedCalendarTask(SelectedCalendarItem.UniqueId);
            var tasks = new List<object> { task };
            var payload = new DragDropViewModel { DraggedItems = tasks, Message = task.Name };
            e.Options.Payload = payload;

            e.Handled = true;
            e.QueryResult = true;
        }

        void OnTasksLoaded(LoadOperation<Task> lo)
        {
            if (lo.HasError)
            {
                Utils.ShowErrorMessage(TasksErrorStrings.Message_LoadingTasksFailed, lo.Error.Message);
                lo.MarkErrorAsHandled();
                return;
            }

            this.OnPropertyChanged(p => p.Tasks);
            this.OnPropertyChanged(p => p.CalendarTasks);
            HasTasks = Tasks.Count() > 0;
            Utils.HideBusyIndicator();
        }

        void OnTaskNotesLoaded(LoadOperation<TaskNote> lo)
        {
            if (lo.HasError)
            {
                Utils.ShowErrorMessage(TasksErrorStrings.Message_LoadingNotesFailed, lo.Error.Message);
                lo.MarkErrorAsHandled();
                return;
            }

            this.OnPropertyChanged(p => p.Notes);
            HasNotes = Notes.Count() > 0;
            Utils.HideBusyIndicator();
        }

        # region Properties

        public EntityType NewItemEntityType
        {
            get { return EntityType.Task; }
        }

        public bool IsInitialized { get; set; }

        public bool IsGridView
        {
            get { return _isGridView; }
            set { _isGridView = value; this.OnPropertyChanged(p => p.IsGridView); }
        }

        public bool IsCalendarView
        {
            get { return _isCalendarView; }
            set { _isCalendarView = value; this.OnPropertyChanged(p => p.IsCalendarView); }
        }

        public bool IsNotFilteredByProject
        {
            get { return SelectedEntityFilterArgs.EntityType != EntityType.Project; }
        }

        public bool IsNotFilteredByContext
        {
            get { return SelectedEntityFilterArgs.EntityType != EntityType.Context; }
        }

        public bool IsNotFilteredByContact
        {
            get { return SelectedEntityFilterArgs.EntityType != EntityType.Contact; }
        }

        public bool IsNotFilteredByCategory
        {
            get { return SelectedEntityFilterArgs.EntityType != EntityType.TaskCategory; }
        }

        public bool HasTasks
        {
            get { return _hasTasks; }
            set { _hasTasks = value; this.OnPropertyChanged(p => p.HasTasks); }
        }

        public bool IsMoveToCommandAvailable
        {
            // get { return SelectedEntityFilterArgs.RelationType == RelationType.TaskCategory; }
            get { return true; }
        }

        public bool IsMoveToInboxCommandAvailable
        {
            get { return IsMoveToCommandAvailable && SelectedEntityFilterArgs.ID != 1; }
        }

        public bool IsMoveToActionsCommandAvailable
        {
            get { return IsMoveToCommandAvailable && SelectedEntityFilterArgs.ID != 2; }
        }

        public bool IsMoveToWaitingCommandAvailable
        {
            get { return IsMoveToCommandAvailable && SelectedEntityFilterArgs.ID != 3; }
        }

        public bool IsMoveToSomedayCommandAvailable
        {
            get { return IsMoveToCommandAvailable && SelectedEntityFilterArgs.ID != 4; }
        }

        public bool IsMoveToTicklersCommandAvailable
        {
            get { return IsMoveToCommandAvailable && SelectedEntityFilterArgs.ID != 5; }
        }

        public bool IsMoveToReferenceCommandAvailable
        {
            get { return IsMoveToCommandAvailable && SelectedEntityFilterArgs.ID != 6; }
        }

        public bool IsSendToCommandAvailable
        {
            // No current rules around this
            get { return true; }
        }

        # endregion

        # region UI Events

        public event RoutedEventHandler ViewGrid;
        public void NotifyViewGrid()
        {
            if (ViewGrid != null) { ViewGrid(this, new RoutedEventArgs()); }
        }

        public event RoutedEventHandler ViewCalendar;
        public void NotifyViewCalendar()
        {
            if (ViewCalendar != null) { ViewCalendar(this, new RoutedEventArgs()); }
        }

        public event RoutedEventHandler TwitterMessage;
        public void NotifyTwitterMessage()
        {
            if (TwitterMessage != null) { TwitterMessage(this, new RoutedEventArgs()); }
        }

        public event RoutedEventHandler CloseTwitterWindow;
        public void NotifyCloseTwitterWindow()
        {
            if (CloseTwitterWindow != null) { CloseTwitterWindow(this, new RoutedEventArgs()); }
        }

        # endregion

        # region Commands

        private RelayCommand<EntityType> _newCommand;
        public RelayCommand<EntityType> NewCommand
        {
            get { return _newCommand ?? (_newCommand = new RelayCommand<EntityType>(OnNew)); }
        }

        private RelayCommand _editCommand;
        public RelayCommand EditCommand
        {
            get { return _editCommand ?? (_editCommand = new RelayCommand(OnEdit)); }
        }

        private RelayCommand _viewGridCommand;
        public RelayCommand ViewGridCommand
        {
            get { return _viewGridCommand ?? (_viewGridCommand = new RelayCommand(OnViewGrid)); }
        }

        private RelayCommand _viewCalendarCommand;
        public RelayCommand ViewCalendarCommand
        {
            get { return _viewCalendarCommand ?? (_viewCalendarCommand = new RelayCommand(OnViewCalendar)); }
        }

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

        private RelayCommand _sendToTwitterCommand;
        public RelayCommand SendToTwitterCommand
        {
            get { return _sendToTwitterCommand ?? (_sendToTwitterCommand = new RelayCommand(OnSendToTwitter)); }
        }

        private RelayCommand _executeSendToTwitterCommand;
        public RelayCommand ExecuteSendToTwitterCommand
        {
            get { return _executeSendToTwitterCommand ?? (_executeSendToTwitterCommand = new RelayCommand(OnExecuteSendToTwitter)); }
        }

        private RelayCommand _closeTwitterWindowCommand;
        public RelayCommand CloseTwitterWindowCommand
        {
            get { return _closeTwitterWindowCommand ?? (_closeTwitterWindowCommand = new RelayCommand(OnCloseTwitterWindow)); }
        }

        private RelayCommand _sendToFacebookCommand;
        public RelayCommand SendToFacebookCommand
        {
            get { return _sendToFacebookCommand ?? (_sendToFacebookCommand = new RelayCommand(OnSendToFacebook)); }
        }

        private RelayCommand<TaskCategoryEnum> _moveToCommand;
        public RelayCommand<TaskCategoryEnum> MoveToCommand
        {
            get { return _moveToCommand ?? (_moveToCommand = new RelayCommand<TaskCategoryEnum>(OnMoveTo)); }
        }

        # endregion

        # region TaskCategoryEnums

        public TaskCategoryEnum TaskCategoryInbox
        {
            get { return TaskCategoryEnum.Inbox; }
        }

        public TaskCategoryEnum TaskCategoryActions
        {
            get { return TaskCategoryEnum.Actions; }
        }

        public TaskCategoryEnum TaskCategoryWaiting
        {
            get { return TaskCategoryEnum.Waiting; }
        }

        public TaskCategoryEnum TaskCategorySomeday
        {
            get { return TaskCategoryEnum.Someday; }
        }

        public TaskCategoryEnum TaskCategoryTicklers
        {
            get { return TaskCategoryEnum.Ticklers; }
        }

        public TaskCategoryEnum TaskCategoryReference
        {
            get { return TaskCategoryEnum.Reference; }
        }

        # endregion

        # region Icons

        public Uri IconNotes
        {
            get { return GetIconUri("Notes"); }
        }

        public Uri IconAttachments
        {
            get { return GetIconUri("Attachments"); }
        }

        public Image IconMarkCompleted
        {
            get { return GetImage("MarkCompleted"); }
        }

        public Image IconTwitter
        {
            get { return GetImage("Twitter"); }
        }

        public Image IconFacebook
        {
            get { return GetImage("Facebook"); }
        }

        public Image IconMoveTo
        {
            get { return GetImage("MoveTo"); }
        }

        public Image IconInbox
        {
            get { return GetImage("Inbox"); }
        }

        public Image IconActions
        {
            get { return GetImage("Actions"); }
        }

        public Image IconWaiting
        {
            get { return GetImage("Waiting"); }
        }

        public Image IconSomeday
        {
            get { return GetImage("Someday"); }
        }

        public Image IconTicklers
        {
            get { return GetImage("Ticklers"); }
        }

        public Image IconReference
        {
            get { return GetImage("Reference"); }
        }

        public Image IconTasks
        {
            get { return GetImage("Tasks"); }
        }

        public Image IconTask
        {
            get { return GetImage("Task"); }
        }

        public Image IconProjects
        {
            get { return GetImage("Projects"); }
        }

        public Image IconProject
        {
            get { return GetImage("Project"); }
        }

        public Image IconContexts
        {
            get { return GetImage("Contexts"); }
        }

        public Image IconContext
        {
            get { return GetImage("Context"); }
        }

        public Image IconPeople
        {
            get { return GetImage("People"); }
        }

        public Image IconPerson
        {
            get { return GetImage("Person"); }
        }

        # endregion

        # region Resource Strings

        public string ResourceCommandMoveTo
        {
            get { return TasksStrings.Command_MoveTo; }
        }

        public string ResourceCommandMoveToInbox
        {
            get { return TasksStrings.Command_MoveToInbox; }
        }

        public string ResourceCommandMoveToActions
        {
            get { return TasksStrings.Command_MoveToActions; }
        }

        public string ResourceCommandMoveToWaiting
        {
            get { return TasksStrings.Command_MoveToWaiting; }
        }

        public string ResourceCommandMoveToSomeday
        {
            get { return TasksStrings.Command_MoveToSomeday; }
        }

        public string ResourceCommandMoveToTicklers
        {
            get { return TasksStrings.Command_MoveToTicklers; }
        }

        public string ResourceCommandMoveToReference
        {
            get { return TasksStrings.Command_MoveToReference; }
        }

        public string ResourceCommandSendTo
        {
            get { return TasksStrings.Command_SendTo; }
        }

        public string ResourceCommandSendToTwitter
        {
            get { return TasksStrings.Command_SendToTwitter; }
        }

        public string ResourceCommandSendToFacebook
        {
            get { return TasksStrings.Command_SendToFacebook; }
        }

        public string ResourceFormLabelContext
        {
            get { return TasksStrings.FormLabel_Context; }
        }

        public string ResourceFormLabelProject
        {
            get { return TasksStrings.FormLabel_Project; }
        }

        public string ResourceFormLabelContact
        {
            get { return TasksStrings.FormLabel_Contact; }
        }

        public string ResourceFormLabelPriority
        {
            get { return TasksStrings.FormLabel_Priority; }
        }

        public string ResourceMessageSaveBeforeAddingNotes
        {
            get { return TasksStrings.Message_SaveBeforeAddingNotes; }
        }

        public string ResourceColumnHeaderName
        {
            get { return TasksStrings.ColumnHeader_Name; }
        }

        public string ResourceColumnHeaderPriority
        {
            get { return TasksStrings.ColumnHeader_Priority; }
        }

        public string ResourceColumnHeaderContext
        {
            get { return TasksStrings.ColumnHeader_Context; }
        }

        public string ResourceColumnHeaderProject
        {
            get { return TasksStrings.ColumnHeader_Project; }
        }

        public string ResourceColumnHeaderContact
        {
            get { return TasksStrings.ColumnHeader_Contact; }
        }

        public string ResourceColumnHeaderCategory
        {
            get { return TasksStrings.ColumnHeader_Category; }
        }

        public string ResourceColumnHeaderDue
        {
            get { return TasksStrings.ColumnHeader_Due; }
        }

        public string ResourceTitleTweetMessage
        {
            get { return TasksStrings.Title_TweetMessage; }
        }

        # endregion

    }
}
