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

namespace XLAB2
{
    internal sealed class CloneVerificationWindowViewModel : ObservableObject
    {
        private string _serialNumbersText;
        private string _statusText;

        public CloneVerificationWindowViewModel(CloneVerificationSeed seed)
        {
            if (seed == null)
            {
                throw new ArgumentNullException("seed");
            }

            SourceSerialNumber = string.IsNullOrWhiteSpace(seed.SourceSerialNumber) ? string.Empty : seed.SourceSerialNumber.Trim();
            VerificationSummary = seed.VerificationSummary ?? string.Empty;

            ConfirmCommand = new RelayCommand(Confirm, CanConfirm);
            CancelCommand = new RelayCommand(Cancel);
            UpdateStatus();
        }

        public event EventHandler<bool?> CloseRequested;

        public ICommand CancelCommand { get; private set; }

        public ICommand ConfirmCommand { get; private set; }

        public string SourceSerialNumber { get; private set; }

        public string SerialNumbersText
        {
            get { return _serialNumbersText; }
            set
            {
                if (SetProperty(ref _serialNumbersText, value))
                {
                    UpdateStatus();
                    ((RelayCommand)ConfirmCommand).RaiseCanExecuteChanged();
                }
            }
        }

        public string StatusText
        {
            get { return _statusText; }
            private set { SetProperty(ref _statusText, value); }
        }

        public string VerificationSummary { get; private set; }

        public IReadOnlyList<string> GetSerialNumbers()
        {
            return ParseSerialNumbers(SerialNumbersText);
        }

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

        private bool CanConfirm(object parameter)
        {
            return ParseSerialNumbers(SerialNumbersText).Count > 0;
        }

        private void Confirm(object parameter)
        {
            RaiseCloseRequested(true);
        }

        private static List<string> ParseSerialNumbers(string value)
        {
            var serialNumbers = new List<string>();
            var unique = new HashSet<string>(StringComparer.OrdinalIgnoreCase);
            if (string.IsNullOrWhiteSpace(value))
            {
                return serialNumbers;
            }

            var separators = new[] { '\r', '\n', '\t', ',', ';' };
            foreach (var token in value.Split(separators, StringSplitOptions.RemoveEmptyEntries))
            {
                var serialNumber = token.Trim();
                if (serialNumber.Length == 0 || !unique.Add(serialNumber))
                {
                    continue;
                }

                serialNumbers.Add(serialNumber);
            }

            return serialNumbers;
        }

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

        private void UpdateStatus()
        {
            var serialCount = ParseSerialNumbers(SerialNumbersText).Count;
            StatusText = string.Format("Уникальных заводских номеров: {0}.", serialCount);
        }
    }
}
