using RX_Sample._04_Final.Call;
using RX_Sample._04_Final.Conctact;
using RX_Sample._03_ReactiveX;
using System;
using System.Linq;
using System.Reactive.Linq;
using System.Reactive.Concurrency;
using System.Collections.Generic;

namespace RX_Sample._04_Final
{
    public sealed class CallInfoViewModel : IDisposable
    {
        private readonly byte[] replacementAvatar = new byte[0];
        private readonly byte[] collaborationAvatar = new byte[0];

        private readonly IDisposable subscription;

        public CallInfoViewModel(
            ICallModel callModel,
            IContactManager contactManager,
            IDispatcher dispatcher,
            IScheduler scheduler)
        {
            var isCollaborationActiveObservable = callModel
                .Collaboration
                .Select(collaboration => collaboration != null);

            var contactAvatarObservable = callModel
                .ContactId
                .Switch(contactId =>
                    contactManager
                        .Contacts
                        .Select(GetContactWithId(contactId))
                        .Switch(GetConctactAvatar)
                );

            subscription = isCollaborationActiveObservable
                .CombineLatest(
                    contactAvatarObservable,
                    (isCollaborationActive, contactAvatar) => isCollaborationActive ? collaborationAvatar : contactAvatar)

                .DistinctUntilChanged()
                .Throttle(TimeSpan.FromSeconds(1), scheduler)
                .Dispatch(dispatcher)
                .Subscribe(avatar => Avatar = avatar);
        }

        private Func<IEnumerable<IContactModel>, IContactModel> GetContactWithId(string contactId)
        {
            return contacts => contacts.FirstOrDefault(c => c.ContactId == contactId);
        }

        private IObservable<byte[]> GetConctactAvatar(IContactModel contact)
        {
            if (contact == null) {
                return Observable.Return<byte[]>(replacementAvatar);
            }

            return contact
                .Avatar
                .Select(o => o ?? replacementAvatar); 
        }

        public byte[] Avatar { get; set; } 

        public void Dispose()
        {
            subscription.Dispose();
        }
    }
}
