using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.ServiceModel.DomainServices.Client;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Messaging;
using TaskIt.Assets.Resources;
using TaskIt.Core;
using TaskIt.Infrastructure;
using TaskIt.Web;

namespace TaskIt.ViewModels
{
    public abstract class TaskItViewModelBase : ViewModelBase
    {
        private bool _isOperationInProgress;
        private bool _isDeletionConfirmed;
        private ItemMode _itemMode = ItemMode.None;
        private string _errorMessage;
        private List<ValidationError> _validationErrors = new List<ValidationError>();
        private List<ValidationResult> _validationResults = new List<ValidationResult>();
        private readonly IDataService _dataService;

        protected TaskItViewModelBase()
        {
            _dataService = new DataService();
        }

        public virtual void OnDelete(Entity entity)
        {
            Messenger.Default.Send(new DeleteEntityArgs(entity));
        }

        public virtual void OnExecuteDelete()
        {
            if (EntityToDelete is Task)
            {
                Utils.DataContext.Tasks.Remove(EntityToDelete);
            }
            if (EntityToDelete is Project)
            {
                Utils.DataContext.Projects.Remove(EntityToDelete);
            }
            else if (EntityToDelete is Context)
            {
                Utils.DataContext.Contexts.Remove(EntityToDelete);
            }
            if (EntityToDelete is Contact)
            {
                Utils.DataContext.Contacts.Remove(EntityToDelete);
            }
            Utils.ShowBusyIndicator();           
            Utils.DataContext.SubmitChanges(OnDeleteCompleted, null);
        }

        public void OnSave(EntityType entityType)
        {
            if (HasValidationErrors())
            {
                FireValidationErrorNotification();
                return;
            }
            ValidationErrors.Clear();            
            Messenger.Default.Send(new SaveEntityArgs(entityType));
            Utils.ShowBusyIndicator();
            Utils.DataContext.SubmitChanges(OnSubmitCompleted, null);
        }

        public void OnAddAttachment()
        {
            // TODO: Ross - Implement
        }

        protected void FireValidationErrorNotification()
        {
            Messenger.Default.Send(ValidationErrors);            
        }

        protected void FireValidationResultNotification()
        {
            Messenger.Default.Send(ValidationResults);
        }

        public void OnBack()
        {
            Utils.DataContext.RejectChanges();
            ValidationErrors.Clear();
            Mode = ItemMode.None;
            Messenger.Default.Send(new DetailsViewCanceledArgs());
        }

        public virtual void OnLoadNotes()
        {
            Utils.ShowBusyIndicator();    
        }

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

            Utils.DataContext.RejectChanges();
            Mode = ItemMode.None;
            Messenger.Default.Send(new DetailsViewCompletedArgs());                        
        }

        public virtual void OnDeleteCompleted(SubmitOperation so)
        {
            Utils.HideBusyIndicator();
            if (so.HasError)
            {
                Utils.ShowErrorMessage(ErrorStrings.Message_SubmitFailed, so.Error.Message);
                so.MarkErrorAsHandled();
                return;
            }

            Utils.DataContext.RejectChanges();
            Mode = ItemMode.None;
            Messenger.Default.Send(new EntityDeletionCompletedArgs());
            Messenger.Default.Send(new DetailsViewCompletedArgs());            
        }

        protected static Uri GetIconUri(string iconName)
        {
            return Utils.GetIconUri(iconName);
        }

        protected static string GetIconPath(string iconName)
        {
            return Utils.GetIconPath(iconName);
        }

        protected static Uri GetLargeIconUri(string iconName)
        {
            return Utils.GetLargeIconUri(iconName);
        }

        protected Image GetImage(string imageName)
        {
            var bitmapImage = new BitmapImage(GetIconUri(imageName));
            return new Image { Source = bitmapImage, Stretch = Stretch.None };
        }

        # region Properties

        public EntitySet<Project> Projects
        {
            get { return Utils.DataContext.Projects; }
        }

        public EntitySet<Context> Contexts
        {
            get { return Utils.DataContext.Contexts; }
        }

        public EntitySet<Contact> Contacts
        {
            get { return Utils.DataContext.Contacts; }
        }

        public EntitySet<Priority> Priorities
        {
            get { return Utils.DataContext.Priorities; }
        }

        public ItemMode Mode
        {
            get { return _itemMode; }
            set
            {
                _itemMode = value; 
                this.OnPropertyChanged(p => p.IsDeleteCommandAvailable);
                this.OnPropertyChanged(p => p.IsAddItemMode);
            }
        }

        public IDataService DataProvider
        {
            get { return _dataService; }
        }

        public bool IsAddItemMode
        {
            get { return _itemMode == ItemMode.Add; }
        }

        public bool IsDeleteCommandAvailable
        {
            get { return Mode == ItemMode.Edit; }
        }

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

        public Visibility ShowRowDetailsTabsToolbar
        {
            get { return Mode == ItemMode.None ? Visibility.Collapsed : Visibility.Visible; }
        }

        public Entity EntityToDelete { get; set; }

        public string ErrorMessage
        {
            get { return _errorMessage; }
            set { _errorMessage = value; this.OnPropertyChanged(p => p.ErrorMessage); }
        }

        public List<ValidationError> ValidationErrors
        {
            get { return _validationErrors; }
            set { _validationErrors = value; this.OnPropertyChanged(p => p.ValidationErrors); }
        }

        public List<ValidationResult> ValidationResults
        {
            get { return _validationResults; }
            set { _validationResults = value; this.OnPropertyChanged(p => p.ValidationResults); }
        }

        public bool HasValidationErrors()
        {
            return ValidationErrors.Count > 0;
        }

        # endregion

        # region UI Events

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

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

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

        # endregion

        # region Commands

        private RelayCommand<Entity> _deleteCommand;
        public RelayCommand<Entity> DeleteCommand
        {
            get { return _deleteCommand ?? (_deleteCommand = new RelayCommand<Entity>(OnDelete)); }
        }

        private RelayCommand _executeDeleteCommand;
        public RelayCommand ExecuteDeleteCommand
        {
            get { return _executeDeleteCommand ?? (_executeDeleteCommand = new RelayCommand(OnExecuteDelete)); }
        }

        private RelayCommand<EntityType> _saveCommand;
        public RelayCommand<EntityType> SaveCommand
        {
            get { return _saveCommand ?? (_saveCommand = new RelayCommand<EntityType>(OnSave)); }
        }

        # endregion

        # region Icons

        public Uri IconNewUri
        {
            get { return GetIconUri("New"); }
        }

        public Uri IconSaveUri
        {
            get { return GetIconUri("Save"); }
        }

        public Uri IconEditUri
        {
            get { return GetIconUri("Edit"); }
        }

        public Uri IconDeleteUri
        {
            get { return GetIconUri("Delete"); }
        }

        public Uri IconBackUri
        {
            get { return GetIconUri("Back"); }
        }

        public Image IconNew
        {
            get { return GetImage("New"); }
        }

        public Image IconSave
        {
            get { return GetImage("Save"); }
        }

        public Image IconEdit
        {
            get { return GetImage("Edit"); }
        }

        public Image IconDelete
        {
            get { return GetImage("Delete"); }
        }

        public Image IconBack
        {
            get { return GetImage("Back"); }
        }

        # endregion

        # region Resource Strings

        public string ResourceTitleApplication
        {
            get { return ApplicationStrings.Title_Application; }
        }

        public string ResourceCommandOK
        {
            get { return CommonStrings.Command_OK; }
        }

        public string ResourceCommandCancel
        {
            get { return CommonStrings.Command_Cancel; }
        }

        public string ResourceCommandClose
        {
            get { return CommonStrings.Command_Close; }
        }

        public string ResourceCommandNew
        {
            get { return CommonStrings.Command_New; }
        }

        public string ResourceCommandEdit
        {
            get { return CommonStrings.Command_Edit; }
        }

        public string ResourceCommandSave
        {
            get { return CommonStrings.Command_Save; }
        }

        public string ResourceCommandDelete
        {
            get { return CommonStrings.Command_Delete; }
        }

        public string ResourceCommandMarkCompleted
        {
            get { return CommonStrings.Command_MarkCompleted; }
        }

        public string ResourceCommandBack
        {
            get { return CommonStrings.Command_Back; }
        }

        public string ResourceFormLabelName
        {
            get { return CommonStrings.FormLabel_Name; }
        }

        public string ResourceFormLabelPassword
        {
            get { return CommonStrings.FormLabel_Password; }
        }

        public string ResourceMessageConfirmDeletion
        {
            get { return CommonStrings.Message_ConfirmDeletion; }
        }

        public string ResourceNoItemsMessage
        {
            get { return CommonStrings.NoItemsMessage; }
        }

        public string ResourceWatermarkName
        {
            get { return CommonStrings.Watermark_Name; }
        }

        # endregion

    }
}