package org.mercury_im.messenger;

import android.content.Context;

import androidx.test.InstrumentationRegistry;
import androidx.test.runner.AndroidJUnit4;

import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.jxmpp.jid.impl.JidCreate;
import org.mercury_im.messenger.xmpp.requery.entity.AccountModel;
import org.mercury_im.messenger.xmpp.requery.entity.ChatModel;
import org.mercury_im.messenger.xmpp.requery.entity.ContactModel;
import org.mercury_im.messenger.xmpp.requery.entity.EntityModel;
import org.mercury_im.messenger.xmpp.requery.entity.LastReadChatMessageRelation;
import org.mercury_im.messenger.xmpp.requery.entity.MessageModel;
import org.mercury_im.messenger.xmpp.requery.entity.Models;
import org.mercury_im.messenger.core.requery.enums.SubscriptionDirection;

import io.reactivex.disposables.Disposable;
import io.reactivex.schedulers.Schedulers;
import io.requery.Persistable;
import io.requery.android.sqlite.DatabaseSource;
import io.requery.reactivex.ReactiveEntityStore;
import io.requery.reactivex.ReactiveSupport;
import io.requery.sql.Configuration;
import io.requery.sql.EntityDataStore;
import io.requery.sql.TableCreationMode;

@RunWith(AndroidJUnit4.class)
public class RequeryDatabaseTest {

    static ReactiveEntityStore<Persistable> dataStore;

    @BeforeClass
    public static void setup() {
        Context appContext = InstrumentationRegistry.getTargetContext();
        DatabaseSource source = new DatabaseSource(appContext, Models.DEFAULT,
                "mercury_test_db", 1);
        // use this in development mode to drop and recreate the tables on every upgrade
        source.setTableCreationMode(TableCreationMode.DROP_CREATE);
        source.setLoggingEnabled(true);
        Configuration configuration = source.getConfiguration();
        dataStore = ReactiveSupport.toReactiveStore(
                new EntityDataStore<>(configuration));
    }

    @Test
    public void databaseTest() throws InterruptedException {
        AccountModel accountModel = new AccountModel();
        accountModel.setJid(JidCreate.entityBareFromOrThrowUnchecked("juliet@capulet.lit"));
        accountModel.setPassword("romeo0romeo");
        accountModel.setRosterVersion(null);
        accountModel.setEnabled(true);

        Disposable accounts = dataStore.select(AccountModel.class).get().observableResult().subscribe(
                accountModels -> accountModels.forEach(System.out::println));

        Disposable entities = dataStore.select(EntityModel.class).get().observableResult()
                .subscribeOn(Schedulers.io())
                .subscribe(entityModels -> entityModels.forEach(System.out::println));

        Disposable contacts = dataStore.select(ContactModel.class).get()
                .observableResult().subscribeOn(Schedulers.io()).subscribe(
                contactModels -> contactModels.forEach(System.out::println));

        Thread.sleep(100);

        dataStore.upsert(accountModel).subscribeOn(Schedulers.io())
                .subscribe();

        ContactModel contactModel = new ContactModel();
        EntityModel entityModel = new EntityModel();
        entityModel.setAccount(accountModel);
        entityModel.setJid(JidCreate.entityBareFromOrThrowUnchecked("romeo@capulet.lit"));
        contactModel.setEntity(entityModel);
        contactModel.setRostername("Romeo");
        contactModel.setSub_direction(SubscriptionDirection.both);
        dataStore.insert(contactModel).blockingGet();

        dataStore.select(AccountModel.ENABLED, ContactModel.ROSTERNAME)
                .from(AccountModel.class)
                .join(EntityModel.class).on(AccountModel.ID.eq(EntityModel.ACCOUNT_ID))
                .join(ContactModel.class).on(EntityModel.ID.eq(ContactModel.ENTITY_ID))
                .get().observableResult().blockingForEach(e -> e.forEach(System.out::println));

        Thread.sleep(10000);
        accounts.dispose();
        entities.dispose();
        contacts.dispose();
    }

    public static class ContactDetail {
        private boolean enabled;
        private String rostername;
    }

    @Test
    public void test2() {
        AccountModel account = new AccountModel();
        account.setJid(JidCreate.entityBareFromOrThrowUnchecked("omemouser@jabberhead.tk"));
        account.setEnabled(true);
        account.setPassword("nöö");

        EntityModel entity = new EntityModel();
        entity.setJid(JidCreate.entityBareFromOrThrowUnchecked("jabbertest@test.test"));
        entity.setAccount(account);

        ContactModel contact = new ContactModel();
        contact.setEntity(entity);
        contact.setRostername("Olaf");
        contact.setSub_direction(SubscriptionDirection.both);
        contact.setSub_approved(false);
        contact.setSub_pending(true);

        dataStore.upsert(contact).blockingGet();

        ChatModel chat = new ChatModel();
        chat.setPeer(entity);
        chat.setDisplayed(true);

        dataStore.upsert(chat).blockingGet();

        MessageModel message = new MessageModel();
        message.setBody("Hallo Welt!");
        message.setChat(chat);

        dataStore.upsert(message).blockingGet();

        LastReadChatMessageRelation lastRead = new LastReadChatMessageRelation();
        lastRead.setChat(chat);
        lastRead.setMessage(message);

        dataStore.upsert(lastRead).blockingGet();

        MessageModel message2 = new MessageModel();
        message2.setChat(chat);
        message2.setBody("How are you?");

        dataStore.upsert(message2).blockingGet();

        LastReadChatMessageRelation lastRead2 = new LastReadChatMessageRelation();
        lastRead2.setChat(chat);
        lastRead2.setMessage(message2);

        dataStore.upsert(lastRead2).blockingGet();
    }
}
