using System;
using System.Collections.Generic;

namespace Valg.EVA.Skanning.ServicesModel.ServiceContracts.Count.Write
{
    public class ResolveDuplicatesInCountingResult
    {
        public bool DuplicatesResolvedSuccessfully { get; }
        public string[] BarcodesForBoxCountingsFailedDelete { get; }
        public string[] BarcodesForBoxCountingFailedStatusUpdate { get; }
        public Exception[] PossibleException { get; }

        private ResolveDuplicatesInCountingResult(bool duplicatesResolvedSuccessfully, string[] barcodesForBoxCountingsFailedDelete = null, string[] barcodesForBoxCountingFailedStatusUpdate = null, Exception[] possibleException = null)
        {
            DuplicatesResolvedSuccessfully = duplicatesResolvedSuccessfully;
            BarcodesForBoxCountingsFailedDelete = barcodesForBoxCountingsFailedDelete;
            BarcodesForBoxCountingFailedStatusUpdate = barcodesForBoxCountingFailedStatusUpdate;
            PossibleException = possibleException;
        }

        private static ResolveDuplicatesInCountingResult Failure(string[] barcodesForBoxCountingsFailedDelete, string[] barcodesForBoxCountingFailedStatusUpdate, Exception[] exceptions)
        {
            return new ResolveDuplicatesInCountingResult(false, barcodesForBoxCountingsFailedDelete, barcodesForBoxCountingFailedStatusUpdate, exceptions);
        }

        internal static ResolveDuplicatesInCountingFailureRecorder FailureRecorder()
        {
            return new ResolveDuplicatesInCountingFailureRecorder();
        }

        public static readonly ResolveDuplicatesInCountingResult Success = new ResolveDuplicatesInCountingResult(true);

        internal class ResolveDuplicatesInCountingFailureRecorder
        {
            private readonly List<string> boxCountingsNotDeleted = new List<string>();
            private readonly List<string> boxCountingsNotStatusUpdated = new List<string>();
            private readonly List<Exception> exceptions = new List<Exception>();
            public bool FailureOccured => boxCountingsNotDeleted.Count > 0 || boxCountingsNotStatusUpdated.Count > 0 || exceptions.Count > 0;

            public void BoxCountingCouldNotBeDeleted(string barcodeLong)
            {
                boxCountingsNotDeleted.Add(barcodeLong);
            }

            public void BoxCountingCouldNotBeUpdatedWithNewStatus(string barcodeLong, Exception exception)
            {
                boxCountingsNotStatusUpdated.Add(barcodeLong);
                exceptions.Add(exception);
            }

            public void ExceptionOccured(Exception exception)
            {
                exceptions.Add(exception);
            }

            public ResolveDuplicatesInCountingResult ToResult()
            {
                return Failure(boxCountingsNotDeleted.ToArray(), boxCountingsNotStatusUpdated.ToArray(), exceptions.ToArray());
            }
        }
    }
}
