using System;
using Valg.EVA.Skanning.Contracts.CommonEnums;
using Valg.EVA.Skanning.Entity.SqlConnection;
using Valg.EVA.Skanning.Repositories.Counting;

namespace Valg.EVA.Skanning.Commands.StartScanning
{
    public class StartScanningCommandHandler : IHandleCommandsWithReturnValue<StartScanningCommand, StartScanningCommandResult>
    {
        private readonly ICountingWriteableRepository countingWriteableRepository;
        private readonly ICountingRepository countingRepository;
        private readonly TransactionScopeFactory transactionScopeFactory;

        public StartScanningCommandHandler(ICountingWriteableRepository countingWriteableRepository,
            ICountingRepository countingRepository, TransactionScopeFactory transactionScopeFactory)
        {
            this.countingWriteableRepository = countingWriteableRepository;
            this.countingRepository = countingRepository;
            this.transactionScopeFactory = transactionScopeFactory;
        }

        public void HandleCommand(StartScanningCommand command)
        {
            CommandResult = new StartScanningCommandResult();

            var boxCounting = countingRepository.GetBoxCounting(command.BarcodeLong, command.BarcodeShort, command.CountingId);

            if (boxCounting == null)
            {
                CommandResult.BoxIsNotReadyForScan = true;
            }
            else
            {
                var readyForScan = boxCounting.State == BoxCountingState.ReadyForScan && boxCounting.Modified == command.BoxCountingConcurrencyToken;

                CommandResult.BoxIsNotReadyForScan = !readyForScan;

                if (readyForScan)
                {
                    using (var scope = transactionScopeFactory.GetTransactionScope())
                    {
                        countingWriteableRepository.UpdateBoxCountingState(
                            command.BarcodeLong,
                            command.BarcodeShort,
                            command.CountingId,
                            BoxCountingState.Scanning,
                            command.BoxCountingConcurrencyToken,
                            BoxCountingState.ReadyForScan,
                            command.ChangedBy);

                        countingWriteableRepository.UpdateBoxCountingWithOriginatingInfo(boxCounting.Id, command.ChangedBy, Environment.MachineName);

                        scope.Complete();
                    }
                }
            }
        }

        public StartScanningCommandResult CommandResult { get; private set; }
    }
}
