using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using Valg.EVA.Skanning.ContainerExtensions;
using Valg.EVA.Skanning.UserInterfaceElements.MainWindowProvider;
using Valg.EVA.Skanning.ServicesModel.Internal;
using Valg.EVA.Skanning.ServicesModel.ServiceContracts.Count.Write;
using Prism.Commands;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.JobManagement.Startup.Data;

namespace Valg.EVA.Skanning.JobManagement.Startup.UI.Duplicates
{
    public class ResolveDuplicatesPopupViewModel : ViewModelBase
    {
        private readonly ITypedFactory typedFactory;
        private readonly IMainWindowProvider mainWindowProvider;
        private ReadOnlyCollection<ResolveDuplicatesBox> allBoxes;
        private ResolveDuplicateAction actionToTake;

        public ReadOnlyCollection<ResolveDuplicatesBox> AllBoxes => allBoxes;

        public ResolveDuplicatesPopupViewModel(ITypedFactory typedFactory, IMainWindowProvider mainWindowProvider)
        {
            this.typedFactory = typedFactory;
            this.mainWindowProvider = mainWindowProvider;

            CancelCommand = new DelegateCommand(() => ActionToTake = ResolveDuplicateAction.NoActionSelected);
        }

        public void Initialize(IReadOnlyCollection<BoxCountingDetailsModel> boxCountings, int countingId)
        {
            allBoxes = boxCountings.Select(bc =>
            {
                var rdb = new ResolveDuplicatesBox(bc.BarcodeLong, bc.BarcodeShort, bc.ConcurrencyToken, bc.Id, bc.ScannedBallots);
                rdb.PropertyChanged += (sender, e) => OnPropertyChanged(null);
                return rdb;
            }).OrderBy(k => k.BoxNumber).ToList().AsReadOnly();

            OpenViewBallotsDialogCommand = new DelegateCommand(() => OpenViewBallotsDialog(countingId));
        }

        private void OpenViewBallotsDialog(int countingId)
        {
            var view = typedFactory.Create<ViewDuplicateBallotsView>();
            var viewModel = typedFactory.Create<ViewDuplicateBallotsViewModel>();
            viewModel.Initialize(countingId, allBoxes);
            
            view.DataContext = viewModel;
            view.Owner = mainWindowProvider.GetMainWindow();
            view.ShowDialog();
        }

        public ResolveDuplicateAction ActionToTake
        {
            get { return actionToTake; }
            set
            {
                actionToTake = value;
                OnPropertyChanged(null);
            }
        }
        public bool IsNoDuplicatesOptionChecked
        {
            get { return ActionToTake == ResolveDuplicateAction.NoDuplicates; }
            set
            {
                if (value)
                {
                    ActionToTake = ResolveDuplicateAction.NoDuplicates;
                }
            }
        }
        public bool IsDeleteAllBoxesOptionChecked
        {
            get { return ActionToTake == ResolveDuplicateAction.DeleteAllBoxes; }
            set
            {
                if (value)
                {
                    ActionToTake = ResolveDuplicateAction.DeleteAllBoxes;
                }
            }
        }
        public bool IsDeleteSomeBoxesOptionChecked
        {
            get { return ActionToTake == ResolveDuplicateAction.DeleteSomeBoxes; }
            set
            {
                if (value)
                {
                    ActionToTake = ResolveDuplicateAction.DeleteSomeBoxes;
                }
            }
        }
        public ICommand CancelCommand { get; }
        public ICommand OpenViewBallotsDialogCommand { get; private set; }

        public bool AreValidOptionsSelected
        {
            get { return IsNoDuplicatesOptionChecked || IsDeleteAllBoxesOptionChecked || (IsDeleteSomeBoxesOptionChecked && AllBoxes.Any(b => b.IsSelectedForDeletion)); }
        }
        public string PossibleDuplicatesInCountingHeader => Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.PossibleDuplicatesInCountingHeader;
        public string ViewDuplicateBallots => Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.ViewDuplicateBallots;
        public string ThereAreNoDuplicates => Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.ThereAreNoDuplicates;
        public string DeleteAllBoxes => Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.DeleteAllBoxes;
        public string DeleteIndividualBoxes => Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.DeleteIndividualBoxes;
        public string CompleteHandlingOfDuplicates => Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.CompleteHandlingOfDuplicates;
        public string Cancel => Resources.Language.LanguageString.Button_Cancel;
        public string PossibleDuplicatesInfoText => Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.PossibleDuplicatesInfoText;
       

        public BoxCountingToResolve[] GetBoxCountingsToDelete()
        {
            return AllBoxes
                .Where(b => ActionToTake == ResolveDuplicateAction.DeleteAllBoxes || (ActionToTake == ResolveDuplicateAction.DeleteSomeBoxes && b.IsSelectedForDeletion))
                .Select(b => new BoxCountingToResolve(b.BarcodeLong, b.BarcodeShort, b.ConcurrencyToken))
                .ToArray();
        }

        public BoxCountingToResolve[] GetBoxCountingsToKeep()
        {
            return AllBoxes
                .Where(b => ActionToTake == ResolveDuplicateAction.NoDuplicates || (ActionToTake == ResolveDuplicateAction.DeleteSomeBoxes && !b.IsSelectedForDeletion))
                .Select(b => new BoxCountingToResolve(b.BarcodeLong, b.BarcodeShort, b.ConcurrencyToken))
                .ToArray();
        }
    }

    public enum ResolveDuplicateAction
    {
        NoActionSelected,
        NoDuplicates,
        DeleteAllBoxes,
        DeleteSomeBoxes
    }

    public class ResolveDuplicatesBox : ViewModelBase
    {
        private bool isSelectedForDeletion;

        public string BoxName => $"{Valg.EVA.Skanning.Resources.Language.JobManagementLanguageString.BoxCounting_BoxName} {BoxNumber}";
        public bool IsSelectedForDeletion
        {
            get { return isSelectedForDeletion; }
            set
            {
                isSelectedForDeletion = value;
                OnPropertyChanged();
            }
        }
        public string BarcodeLong { get; }
        public string BarcodeShort { get; }
        public DateTime ConcurrencyToken { get; }
        public int Id { get; }
        public int ScannedBallots { get; }
        public int BoxNumber { get; }

        public ResolveDuplicatesBox(string barcodeLong, string barcodeShort, DateTime concurrencyToken, int id, int scannedBallots)
        {
            BoxNumber = barcodeLong.GetBoxNumberFromBarcodeLong();
            BarcodeLong = barcodeLong;
            BarcodeShort = barcodeShort;
            ConcurrencyToken = concurrencyToken;
            Id = id;
            ScannedBallots = scannedBallots;
        }
    }
}
