using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Input;

namespace XLAB
{
    internal sealed class TprmcpEditWindowViewModel : ObservableObject
    {
        private readonly IReadOnlyList<TprmcpDirectoryItem> _existingItems;
        private int _cycleId;
        private string _comment;
        private int _groupId;
        private string _periodMonthsText;
        private string _validationMessage;

        public TprmcpEditWindowViewModel(TprmcpDirectoryItem seed, bool isNew, IReadOnlyList<TprmcpDirectoryItem> existingItems, TypeSizeDirectoryService service)
        {
            var source = seed ?? new TprmcpDirectoryItem();
            _existingItems = existingItems ?? Array.Empty<TprmcpDirectoryItem>();
            Id = source.Id;
            TypeSizeId = source.TypeSizeId;
            IsNew = isNew;
            CycleItems = new[] { new DirectoryLookupItem { Id = 0, Name = string.Empty } }.Concat(service.LoadSpvdmcReferences()).ToList();
            GroupItems = new[] { new DirectoryLookupItem { Id = 0, Name = string.Empty } }.Concat(service.LoadGrsiReferences()).ToList();
            CycleId = source.CycleId ?? 0;
            GroupId = source.GroupId ?? 0;
            PeriodMonthsText = source.PeriodMonths.ToString();
            Comment = source.Comment ?? string.Empty;
            ConfirmCommand = new RelayCommand(Confirm);
            CancelCommand = new RelayCommand(Cancel);
        }

        public event EventHandler<bool?> CloseRequested;
        public ICommand CancelCommand { get; private set; }
        public ICommand ConfirmCommand { get; private set; }
        public IReadOnlyList<DirectoryLookupItem> CycleItems { get; private set; }
        public IReadOnlyList<DirectoryLookupItem> GroupItems { get; private set; }
        public int Id { get; private set; }
        public bool IsNew { get; private set; }
        public int TypeSizeId { get; private set; }
        public int CycleId { get { return _cycleId; } set { SetProperty(ref _cycleId, value); } }
        public int GroupId { get { return _groupId; } set { SetProperty(ref _groupId, value); } }
        public string PeriodMonthsText { get { return _periodMonthsText; } set { SetProperty(ref _periodMonthsText, value); } }
        public string Comment { get { return _comment; } set { SetProperty(ref _comment, value); } }
        public string Title { get { return IsNew ? "Новый период МК" : "Редактирование периода МК"; } }
        public string ValidationMessage { get { return _validationMessage; } private set { SetProperty(ref _validationMessage, value); } }

        public TprmcpDirectoryItem ToResult()
        {
            return new TprmcpDirectoryItem
            {
                Id = Id,
                TypeSizeId = TypeSizeId,
                CycleId = CycleId > 0 ? (int?)CycleId : null,
                GroupId = GroupId > 0 ? (int?)GroupId : null,
                PeriodMonths = int.Parse(PeriodMonthsText.Trim()),
                Comment = Normalize(Comment)
            };
        }

        private void Cancel(object parameter) { RaiseCloseRequested(false); }

        private void Confirm(object parameter)
        {
            int periodMonths;
            if (!int.TryParse((PeriodMonthsText ?? string.Empty).Trim(), out periodMonths))
            {
                ValidationMessage = "Период МК должен быть целым числом.";
                return;
            }

            var duplicate = _existingItems.FirstOrDefault(delegate(TprmcpDirectoryItem item)
            {
                return item != null
                       && item.Id != Id
                       && item.CycleId == (CycleId > 0 ? (int?)CycleId : null)
                       && item.GroupId == (GroupId > 0 ? (int?)GroupId : null)
                       && item.PeriodMonths == periodMonths;
            });
            if (duplicate != null)
            {
                ValidationMessage = "Такой цикл и период МК уже существуют для выбранного типоразмера.";
                return;
            }

            ValidationMessage = string.Empty;
            RaiseCloseRequested(true);
        }

        private static string Normalize(string value) { return string.IsNullOrWhiteSpace(value) ? string.Empty : value.Trim(); }

        private void RaiseCloseRequested(bool? dialogResult)
        {
            var handler = CloseRequested;
            if (handler != null) handler(this, dialogResult);
        }
    }
}
