using System;
using System.Windows;
using Valg.EVA.Skanning.ContainerExtensions;
using Valg.Eva.Skanning.Scan.Presentation.ErrorHandling;
using Valg.Eva.Skanning.Scan.Presentation.ScanInProgress;
using Valg.EVA.Skanning.Scan.ReadSoftContracts.Events;
using Valg.EVA.Skanning.UserInterfaceElements.LightBox;
using Valg.EVA.Skanning.UserInterfaceElements.MessageBox;
using Prism.Commands;
using Prism.Events;
using Valg.EVA.Skanning.Diagnostics;
using Valg.EVA.Skanning.UserInterfaceElements.ApplicationTermination;

namespace Valg.EVA.Skanning.Scan.Api
{
    public class RecoverableReadsoftErrorsDispatcher
    {
        private readonly IEventAggregator eventAggregator;
        private readonly ITypedFactory typedFactory;
        private bool scanMoreBallotsWasRequested;

        public RecoverableReadsoftErrorsDispatcher(IEventAggregator eventAggregator, ITypedFactory typedFactory)
        {
            this.eventAggregator = eventAggregator;
            this.typedFactory = typedFactory;
            SubscribeToViewModelEvents();
        }

        public void DispatchAppError(int errorNo, int errorType, int errorId, int errorIdExt, ScanApplication scanApplication)
        {
            var readSoftErrorCode = (ReadSoftErrorCode)errorNo;
            if (readSoftErrorCode == ReadSoftErrorCode.PaperJam)
            {
                eventAggregator.GetEvent<ScanReportedPaperJamEvent>().Publish(new ScanReportedPaperJamEventArgs());
            }
            else if (readSoftErrorCode == ReadSoftErrorCode.CannotOpenDatabase)
            {
                HandleCannotOpenDatabaseError();
            }
            else
            {
                DispatchUnspecificReadsoftError(scanApplication, new ReadSoftException(readSoftErrorCode));
            }
        }

        private void HandleCannotOpenDatabaseError()
        {
            var resultDialog = typedFactory.Create<IMessageBox>();

            resultDialog.Initialize(
                Resources.Language.ScanLanguageString.ReadSoft_CannotOpenDatabaseTitle,
                Resources.Language.ScanLanguageString.ReadSoft_CannotOpenDatabaseDetails,
                Resources.Language.ScanLanguageString.ReadSoft_CannotOpenDatabaseSolution,
                MessageBoxType.Error, null, new DelegateCommand(CloseApplication));

            var eventArgs = new LightBoxEventArgs(resultDialog as Window);
            eventAggregator.GetEvent<ShowLightBoxEvent>().Publish(eventArgs);
        }

        private void CloseApplication()
        {
            var terminateRequestedEvent = eventAggregator.GetEvent<ApplicationTerminateRequestedEvent>();
            terminateRequestedEvent.Publish(EventArgs.Empty);
        }

        public void DispatchScanNotifyUserError(int errorSituation, string errorInfo, ScanApplication scanApplication)
        {
            var notifyUserErrorType = (NotifyUserErrorType)errorSituation;
            if (notifyUserErrorType == NotifyUserErrorType.NoMorePaperInTheAutomaticDocumentFeeder)
            {
                var scanReportedNoMorePaperInFeederEventArgs = new ScanReportedNoMorePaperInFeederEventArgs();
                scanReportedNoMorePaperInFeederEventArgs.ScanMoreBallotsWasRequested = scanMoreBallotsWasRequested;
                eventAggregator.GetEvent<ScanReportedNoMorePaperInFeederEvent>().Publish(scanReportedNoMorePaperInFeederEventArgs);
                scanMoreBallotsWasRequested = false;

                scanApplication.StopJob();
            }
            else
            {
                DispatchUnspecificReadsoftError(scanApplication, new ReadSoftException(notifyUserErrorType, errorInfo));
            }
        }

        public void DispatchGenericException(Exception exception, ScanApplication scanApplication)
        {
            DispatchUnspecificReadsoftError(scanApplication, new ReadSoftException(exception));
        }

        public void DispatchJobSetupError(ScanApplication scanApplication)
        {
            EvaSkanningEventSource.Log.NotSupportedBatchSettingInReadsoftIsUsed();
            scanApplication.StopJob();
            eventAggregator.GetEvent<ScanReportedBatchInUseForJobErrorEvent>().Publish(new ScanReportedBatchInUseForJobErrorEventArgs());
        }

        private void DispatchUnspecificReadsoftError(ScanApplication scanApplication, ReadSoftException readSoftException)
        {
            EvaSkanningEventSource.Log.ErrorFromReadsoft(readSoftException.ToString());

            scanApplication.StopJob();

            eventAggregator.GetEvent<ScanReportedUnspecificReadsoftErrorCodeEvent>().Publish(new ScanReportedUnspecificReadsoftErrorCodeEventArgs());
        }

        private void SubscribeToViewModelEvents()
        {
            eventAggregator.GetEvent<ScanMoreBallotsWasRequestedEvent>().Subscribe(args => ScanMoreBallotsWasRequested());
            eventAggregator.GetEvent<AnotherBallotWasScannedEvent>().Subscribe(args => AnotherBallotWasScanned());
        }

        private void AnotherBallotWasScanned()
        {
            scanMoreBallotsWasRequested = false;
        }

        private void ScanMoreBallotsWasRequested()
        {
            scanMoreBallotsWasRequested = true;
        }
    }
}

