using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using Valg.EVA.Skanning.Entity.ReadModel;
using Valg.EVA.Skanning.Entity.SerializedEntities.CountResultModel;
using Valg.EVA.Skanning.Identity;
using Valg.EVA.Skanning.Repositories.BallotPaper;
using Valg.EVA.Skanning.Repositories.Counting;
using Valg.EVA.Skanning.Services.Verification;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.DataProvider;
using Valg.EVA.Skanning.ServicesModel.ElectionConfig.Model;
using Valg.EVA.Skanning.ServicesModel.Internal.CountResult;
using Valg.EVA.Skanning.UserInterfaceElements;
using Valg.EVA.Skanning.UserInterfaceElements.BallotPaperImage;

namespace Valg.EVA.Skanning.Sample.Startup.Ballot
{
    public class BallotControlViewModel : ViewModelBase
    {
        private int _ballotPaperId;
        private int _boxId;
        private readonly IVerificationService _verificationService;
        private readonly IIdentityProvider _identityProvider;
        private readonly IBallotPaperImageViewModel ballotPaperImageViewModel;
        private readonly CastVoteMapper _castVoteMapper;
        private readonly CountingRepository _countingRepository;
        private Counting _counting;
        private ReadOnlyCollection<CastVote> _castVotes;
        private readonly ICandidateListDataProvider _candidateListDataProvider;
        private List<Affiliation> _affiliations;
        private readonly IBallotPaperRepository _ballotPaperRepository;

        public BallotControlViewModel(
            IVerificationService verificationService,
            IIdentityProvider identityProvider,
            IBallotPaperImageViewModel ballotPaperImageViewModel,
            CastVoteMapper castVoteMapper,
            CountingRepository countingRepository,
            ICandidateListDataProvider candidateListDataProvider,
            IBallotPaperRepository ballotPaperRepository)
        {
            _candidateListDataProvider = candidateListDataProvider;
            _countingRepository = countingRepository;
            _castVoteMapper = castVoteMapper;
            _verificationService = verificationService;
            _identityProvider = identityProvider;
            this.ballotPaperImageViewModel = ballotPaperImageViewModel;
            _ballotPaperRepository = ballotPaperRepository;
        }

        public BallotOverview BallotOverview { get; } = new BallotOverview();

        public int BoxId
        {
            get => _boxId;
            set
            {
                _boxId = value;
                _counting = _countingRepository.GetCountingByBoxCountingId(_boxId);
                _castVotes = _castVoteMapper.MapToCastVotes(_counting, _identityProvider?.CurrentSelectedRole?.ReportingUnitIdentifier);
            }
        }
        public int BallotPaperId
        {
            get => _ballotPaperId;
            set
            {
                _ballotPaperId = value;
                SetUpImageViewModel();
                GetBallotOverviewStatus();
            }
        }

        public IBallotPaperImageViewModel BallotPaperImageViewModel => ballotPaperImageViewModel;

        private void SetUpImageViewModel()
        {
            var loader = new BallotPaperImageLoader(_verificationService, _identityProvider);
            var bitmapInfo = loader.GetBallotPaperBitmaps(_ballotPaperId, null);
            var desiredHeight = 2 * System.Windows.SystemParameters.PrimaryScreenHeight / 3;
            var scaleFactor = desiredHeight / bitmapInfo.Front.Height; 
            ballotPaperImageViewModel.BallotPaperId = _ballotPaperId;
            ballotPaperImageViewModel.BoxCountingId = -1; 
            ballotPaperImageViewModel.Front = new TransformedBitmap(bitmapInfo.Front, new ScaleTransform(scaleFactor, scaleFactor));
            ballotPaperImageViewModel.Back = new TransformedBitmap(bitmapInfo.Back, new ScaleTransform(scaleFactor, scaleFactor));
            ballotPaperImageViewModel.Selected = ballotPaperImageViewModel.Front;
            ballotPaperImageViewModel.ShowZoomPanelMiniMap = true;
            ballotPaperImageViewModel.CurrentBallotPaperImageIndex = 0;
            OnPropertyChanged(nameof(BallotPaperImageViewModel));

        }

        private void GetBallotOverviewStatus()
        {
            BallotOverview.AffiliationId = null;
            BallotOverview.RejectionReason = CastVote.RejectionReasonCode.NotRejected;
            BallotOverview.AutomaticallyVerified = false;
            BallotOverview.PersonVotes.Clear();
            BallotOverview.WriteInVotes.Clear();
            BallotOverview.Strikeouts.Clear();
            BallotOverview.Renumberings.Clear();

            _affiliations = _candidateListDataProvider.GetAffiliations(_identityProvider.CurrentSelectedRole.Area.ElectionEventId, _identityProvider.CurrentSelectedRole.ContestId);
            var castVote = _castVotes?.SingleOrDefault(f => f.BallotDbId == BallotPaperId);
            if (castVote == null)
            {
                OnPropertyChanged(nameof(BallotOverview));
                return;
            }

            BallotOverview.RejectionReason = castVote.ProposedRejection;
            BallotOverview.AffiliationId = castVote.AffiliationIdentifier?.AffiliationId;

            foreach (var pv in castVote.PersonalVotes)
            {
                var candidateName = GetCandidateName(pv.RankInAffiliation, castVote.AffiliationIdentifier?.AffiliationId);
                BallotOverview.PersonVotes.Add(new PersonVote(){CandidateName = candidateName, CandidateNumber = int.Parse(pv.RankInAffiliation)});
            }
            foreach (var wi in castVote.WriteIns)
            {
                var candidateName = GetCandidateName(wi.RankInAffiliation, wi.AffiliationIdentifier?.AffiliationId);
                BallotOverview.WriteInVotes.Add(new WriteInVote() { CandidateName = candidateName, AffiliationId = wi.AffiliationIdentifier?.AffiliationId});
            }

            var originalBallotPaperValues = _ballotPaperRepository.GetOriginalBallotPaperValues(castVote.BallotDbId);
            var currentBallotPaperValues = _ballotPaperRepository.GetCurrentBallotPaperValues(castVote.BallotDbId);

            if (!originalBallotPaperValues.NeededVerification && castVote.ProposedRejection == CastVote.RejectionReasonCode.NotRejected)
            {
                BallotOverview.AutomaticallyVerified = true;
            }
            OnPropertyChanged(nameof(BallotOverview));
        }

        private string GetCandidateName(string rankInAffiliation, string affiliationId)
        {
            return _affiliations.FirstOrDefault(p => p.AffiliationId == affiliationId)?.Candidates.FirstOrDefault(p => p.RankInAffiliation == Convert.ToInt32(rankInAffiliation))?.NameLine;
        }


    }
}

