package org.mercury_im.messenger.data.di;

import org.mercury_im.messenger.data.mapping.AccountMapping;
import org.mercury_im.messenger.data.mapping.DirectChatMapping;
import org.mercury_im.messenger.data.mapping.EntityCapsMapping;
import org.mercury_im.messenger.data.mapping.GroupChatMapping;
import org.mercury_im.messenger.data.mapping.MessageMapping;
import org.mercury_im.messenger.data.mapping.PeerMapping;
import org.mercury_im.messenger.data.repository.AccountRepository;
import org.mercury_im.messenger.data.repository.EntityCapsRepository;
import org.mercury_im.messenger.data.repository.GroupChatRepository;
import org.mercury_im.messenger.data.repository.MessageRepository;
import org.mercury_im.messenger.data.repository.PeerRepository;
import org.mercury_im.messenger.data.repository.DirectChatRepository;
import org.mercury_im.messenger.data.repository.XmppEntityCapsRepository;
import org.mercury_im.messenger.data.repository.Repositories;
import org.mercury_im.messenger.data.repository.XmppAccountRepository;
import org.mercury_im.messenger.data.repository.XmppDirectChatRepository;
import org.mercury_im.messenger.data.repository.XmppGroupChatRepository;
import org.mercury_im.messenger.data.repository.XmppMessageRepository;
import org.mercury_im.messenger.data.repository.XmppPeerRepository;
import org.mercury_im.messenger.util.ThreadUtils;

import javax.inject.Named;
import javax.inject.Singleton;

import dagger.Module;
import dagger.Provides;
import io.reactivex.Scheduler;
import io.requery.Persistable;
import io.requery.reactivex.ReactiveEntityStore;

@Module(includes = {
        MappingModule.class,
        DaoModule.class
})
public class RepositoryModule {

    @Provides
    @Singleton
    static AccountRepository provideAccountRepository(
            ReactiveEntityStore<Persistable> data,
            @Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
            @Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler,
            AccountMapping accountMapping) {
        return new XmppAccountRepository(data, ioScheduler, uiScheduler, accountMapping);
    }

    @Provides
    @Singleton
    static PeerRepository providePeerRepository(
            ReactiveEntityStore<Persistable> data,
            @Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
            @Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler,
            PeerMapping peerMapping,
            AccountRepository accountRepository) {
        return new XmppPeerRepository(data, ioScheduler, uiScheduler, peerMapping, accountRepository);
    }

    @Provides
    @Singleton
    static DirectChatRepository provideDirectChatRepository(
            ReactiveEntityStore<Persistable> data,
            @Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
            @Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler,
            DirectChatMapping directChatMapping) {
        return new XmppDirectChatRepository(data, ioScheduler, uiScheduler, directChatMapping);
    }

    @Provides
    @Singleton
    static GroupChatRepository provideGroupChatRepository(
            ReactiveEntityStore<Persistable> data,
            @Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
            @Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler,
            GroupChatMapping groupChatMapping) {
        return new XmppGroupChatRepository(data, ioScheduler, uiScheduler, groupChatMapping);
    }

    @Provides
    @Singleton
    static MessageRepository provideMessageRepository(
            ReactiveEntityStore<Persistable> data,
            @Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
            @Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler,
            MessageMapping messageMapping,
            DirectChatMapping directChatMapping,
            GroupChatMapping groupChatMapping) {
        return new XmppMessageRepository(data, ioScheduler, uiScheduler,
                messageMapping, directChatMapping, groupChatMapping);
    }

    @Provides
    @Singleton
    static EntityCapsRepository provideCapsRepository(
            ReactiveEntityStore<Persistable> data,
            @Named(value = ThreadUtils.SCHEDULER_IO) Scheduler ioScheduler,
            @Named(value = ThreadUtils.SCHEDULER_UI) Scheduler uiScheduler,
            EntityCapsMapping entityCapsMapping) {
        return new XmppEntityCapsRepository(data, ioScheduler, uiScheduler, entityCapsMapping);
    }

    @Provides
    @Singleton
    static Repositories provideRepositories(
            AccountRepository accountRepository,
            DirectChatRepository directChatRepository,
            GroupChatRepository groupChatRepository,
            MessageRepository messageRepository,
            PeerRepository peerRepository,
            XmppEntityCapsRepository entityCapsRepository) {
        return new Repositories(accountRepository, directChatRepository, groupChatRepository,
                messageRepository, peerRepository, entityCapsRepository);
    }
}
