using System;
using System.ComponentModel;
using System.Windows.Input;
using KellermanSoftware.ContactsModule.DataAccess;
using KellermanSoftware.ContactsModule.Models;
using Microsoft.Practices.Prism.Commands;
using Microsoft.Practices.Prism.ViewModel;

namespace KellermanSoftware.ContactsModule.ViewModels
{
    public sealed class EditContactDetailsViewModel : NotificationObject, 
                                                      IDataErrorInfo
    {
        private readonly IRepository _repository;
        private readonly IContactsViewModel _contactsViewModel;
        private readonly DelegateCommand _saveCommand;
        private readonly Contact _contact;

        public EditContactDetailsViewModel(IRepository repository,
                                           IContactsViewModel contactsViewModel,
                                           Contact contact)
        {
            if (repository == null)
            {
                throw new ArgumentNullException("repository");
            }
            if (contactsViewModel == null)
            {
                throw new ArgumentNullException("contactsViewModel");
            }

            _repository = repository;
            _contactsViewModel = contactsViewModel;
            _contact = contact;

            _saveCommand = new DelegateCommand(SaveContact, CanSaveContact);
        }

        public ICommand SaveCommand
        {
            get { return _saveCommand; }
        }

        public string Name
        {
            get { return _contact.Name; }
            set
            {
                if (value != _contact.Name)
                {
                    _contact.Name = value;
                    RaisePropertyChanged(() => Name);
                    _saveCommand.RaiseCanExecuteChanged();
                }
            }
        }

        public string Address
        {
            get { return _contact.Address; }
            set
            {
                if (value != _contact.Address)
                {
                    _contact.Address = value;
                    RaisePropertyChanged(() => Address);
                }
            }
        }

        public string City
        {
            get { return _contact.City; }
            set
            {
                if (value != _contact.City)
                {
                    _contact.City = value;
                    RaisePropertyChanged(() => City);
                }
            }
        }

        public string State
        {
            get { return _contact.State; }
            set
            {
                if (value != _contact.State)
                {
                    _contact.State = value;
                    RaisePropertyChanged(() => State);
                }
            }
        }

        public string PostalCode
        {
            get { return _contact.PostalCode; }
            set
            {
                if (value != _contact.PostalCode)
                {
                    _contact.PostalCode = value;
                    RaisePropertyChanged(() => PostalCode);
                }
            }
        }

        public string Country
        {
            get { return _contact.Country; }
            set
            {
                if (value != _contact.Country)
                {
                    _contact.Country = value;
                    RaisePropertyChanged(() => Country);
                }
            }
        }

        public string Email
        {
            get { return _contact.Email; }
            set
            {
                if (value != _contact.Email)
                {
                    _contact.Email = value;
                    RaisePropertyChanged(() => Email);
                }
            }
        }

        public string Phone
        {
            get { return _contact.Phone; }
            set
            {
                if (value != _contact.Phone)
                {
                    _contact.Phone = value;
                    RaisePropertyChanged(() => Phone);
                }
            }
        }

        #region IDataErrorInfo Members

        // WPF doesn't use this property.
        public string Error
        {
            get
            {
                throw new NotImplementedException();
            }
        }

        public string this[string columnName]
        {
            get
            {
                string error = null;
                switch (columnName)
                {
                    case "Name":
                        var result = _contact.ValidateName();
                        if (!result.Item1)
                        {
                            error = result.Item2;
                        }
                        break;
                }
                return error;
            }
        }

        #endregion IDataErrorInfo Members

        private void SaveContact()
        {
            _repository.SaveContact(_contact);
            _contactsViewModel.ReloadContactsList(_contact.ContactId);
        }

        private bool CanSaveContact()
        {
            return _contact.ValidateName().Item1;
        }
    }
}
