using System;
using System.ComponentModel;
using System.Globalization;
using System.Windows.Input;
using Valg.EVA.Skanning.UserInterfaceElements.TopBar;
using Prism.Commands;
using Valg.Eva.Skanning.Scan.Presentation.MainWindow;
using Valg.EVA.Skanning.UserInterfaceElements;

namespace Valg.Eva.Skanning.Scan.Presentation.BoxInfo
{
    public class BoxInfoViewModel : ViewModelBase, IBoxInfoViewModel
    {
        private readonly ICommand startScanningCommand;
        private BoxViewModel boxViewModel;
        private readonly ICommand reregisterBoxCommand;
        private readonly ICommand registerBoxAsEmptyCommand;
        private bool isStartScanningButtonFocused;
        private BoxScanningSession currentSession;

        public BoxInfoViewModel()
        {
            startScanningCommand = new DelegateCommand(PublishStartScanningEvent);
            reregisterBoxCommand = new DelegateCommand(PublishReregisterBoxEvent);
            registerBoxAsEmptyCommand = new DelegateCommand(PublishRegisterBoxAsEmptyEvent);
        }

        protected override void SubscribeToViewModelSpecificEvents()
        {
            SubscribeToEvent<ScanningMainPageChangedEvent, ScanningMainPageChangedEventArgs>(SetStartButtonFocus);
        }

        private void SetStartButtonFocus(ScanningMainPageChangedEventArgs scanningMainPageChangedEventArgs)
        {
            if (scanningMainPageChangedEventArgs.NewIndex == MainTabIndexes.BoxInfoPageIndex)
            {
                DelayedFocusSetter.SetFocus(() => IsStartScanningButtonFocused = true);
            }
            else
            {
                IsStartScanningButtonFocused = false;
            }
        }

        private void PublishRegisterBoxAsEmptyEvent()
        {
            PublishEvent<RegisterBoxAsEmptyEvent,RegisterBoxAsEmptyEventArgs>(new RegisterBoxAsEmptyEventArgs());
        }

        private void PublishReregisterBoxEvent()
        {
            PublishEvent<SetReadyForAcceptingBarcodesEvent, SetReadyForAcceptingBarcodesEventArgs>(new SetReadyForAcceptingBarcodesEventArgs());
        }

        private void PublishStartScanningEvent()
        {
            PublishEvent<StartScanningEvent, StartScanningEventArgs>(new StartScanningEventArgs());
        }

        public ICommand StartScanningCommand
        {
            get { return startScanningCommand; }
        }

        public string StartScanningButtonText
        {
            get { return Valg.EVA.Skanning.Resources.Language.ScanLanguageString.Button_StartScanning; }
        }
        public string BoxRegisteredText
        {
            get { return Valg.EVA.Skanning.Resources.Language.ScanLanguageString.BoxRegistered; }
        }
        public string Barcode1Text
        {
            get { return Valg.EVA.Skanning.Resources.Language.ScanLanguageString.Barcode1; }
        }

        public string GetValueOrEmptyIfNull<T>(T obj, Func<T, string> propertyAccessor) where T : class
        {
            return obj != null ? propertyAccessor.Invoke(obj) : string.Empty;
        }

        public string Barcode1
        {
            get
            {
                return GetValueOrEmptyIfNull(boxViewModel, b => b.BarcodeLong);
            }
        }

        public string Barcode2Text
        {
            get { return Valg.EVA.Skanning.Resources.Language.ScanLanguageString.Barcode2; }
        }

        public string Barcode2
        {
            get
            {
                return GetValueOrEmptyIfNull(boxViewModel, b => b.BarcodeShort);
            }
        }

        public string ReregisterBoxButtonText
        {
            get { return Valg.EVA.Skanning.Resources.Language.ScanLanguageString.ReregisterBoxText; }
        }

        public string RegisterBoxAsEmptyText
        {
            get { return Valg.EVA.Skanning.Resources.Language.ScanLanguageString.RegisterBoxAsEmptyText; }
        }

        public string BoxNumberAndCountHeaderText
        {
            get
            {
                return string.Format("{0} {1} {2} {3} - {4}",
                    Valg.EVA.Skanning.Resources.Language.VerifyLanguageString.Box,
                    GetValueOrEmptyIfNull(boxViewModel, b => b.BoxNumber.ToString(CultureInfo.InvariantCulture)),
                    Valg.EVA.Skanning.Resources.Language.LanguageString.Of,
                    GetValueOrEmptyIfNull(boxViewModel, b => b.TotalBoxes.ToString(CultureInfo.InvariantCulture)),
                    Valg.EVA.Skanning.Resources.Language.LanguageString.ReadyForScanning);
            }
        }

        public string BoxElectionText
        {
            get { return Valg.EVA.Skanning.Resources.Language.LanguageString.Label_Election + ":"; }
        }

        public string BoxCountyText
        {
            get { return Valg.EVA.Skanning.Resources.Language.LanguageString.County + ":"; }
        }

        public string BoxMunicipalityText
        {
            get { return Valg.EVA.Skanning.Resources.Language.LanguageString.Label_Municipality + ":"; }
        }

        public string BoxPollingDistrictText
        {
            get { return Valg.EVA.Skanning.Resources.Language.LanguageString.Label_PollingDistrict + ":"; }
        }
        
        public string CountingText
        {
            get { return Valg.EVA.Skanning.Resources.Language.LanguageString.Counting + ":"; }
        }

        public string BoxVotingCategoryText
        {
            get { return Valg.EVA.Skanning.Resources.Language.LanguageString.Label_Category + ":"; }
        }
        public string BoxElection
        {
            get { return GetValueOrEmptyIfNull(boxViewModel, b => b.Election); }
        }
        public string BoxCounty
        {
            get { return GetValueOrEmptyIfNull(boxViewModel, b => b.County); }
        }
        public string BoxMunicipality
        {
            get { return GetValueOrEmptyIfNull(boxViewModel, b => b.Municipality); }
        }
        public string BoxPollingDistrict
        {
            get { return GetValueOrEmptyIfNull(boxViewModel, b => b.PollingDistrict); }
        }
        public string BoxCategory
        {
            get { return GetValueOrEmptyIfNull(boxViewModel, b => b.Category); }
        }
        public string Counting
        {
            get { return GetValueOrEmptyIfNull(boxViewModel, b => b.CountingName); }
        }
        public ICommand ReregisterBoxCommand
        {
            get { return reregisterBoxCommand; }
        }
        public ICommand RegisterBoxAsEmptyCommand
        {
            get { return registerBoxAsEmptyCommand; }
        }
        public bool IsStartScanningButtonFocused
        {
            get { return isStartScanningButtonFocused; }
            set
            {
                isStartScanningButtonFocused = value;
                OnPropertyChanged();
            }
        }

        public void AttachToModel(BoxScanningSession currentScanningSession)
        {
            if (currentSession != null)
            {
                currentSession.PropertyChanged -= CurrentScanningSessionOnPropertyChanged;
            }

            currentSession = currentScanningSession;

            if (currentSession != null)
            {
                currentSession.PropertyChanged += CurrentScanningSessionOnPropertyChanged;
                CreateNewBoxViewModel();
                SetDataOnBoxCountingInformationView();
            }
        }
        

        private void CurrentScanningSessionOnPropertyChanged(object sender, PropertyChangedEventArgs propertyChangedEventArgs)
        {
            if (propertyChangedEventArgs.PropertyName == PropertyHelper.GetName<BoxScanningSession>(b => b.Box))
            {
                CreateNewBoxViewModel();
            }
        }

        private void CreateNewBoxViewModel()
        {
            boxViewModel = new BoxViewModel(currentSession.Box);
            
            OnPropertyChanged(null);
        }

        private void SetDataOnBoxCountingInformationView()
        {            
            var box = currentSession.Box;
            var eventArgs = new BoxCountingInformationViewSetDataEventArgs(box.Category, box.BoxNumber, box.PollingDistrict, box.BoxCounting.CountingType,currentSession.Box.BoxCounting.CountNumber);
            PublishEvent<BoxCountingInformationViewSetDataEvent, BoxCountingInformationViewSetDataEventArgs>(eventArgs);
        }
    }
}
