package com.raizlabs.android.dbflow.test.concurrent;

import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.sql.language.Delete;
import com.raizlabs.android.dbflow.sql.language.Insert;
import com.raizlabs.android.dbflow.sql.language.SQLite;
import com.raizlabs.android.dbflow.test.FlowTestCase;
import com.raizlabs.android.dbflow.test.TestDatabase;
import com.raizlabs.android.dbflow.test.structure.TestModel1;

import org.junit.Test;

import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;

import static com.raizlabs.android.dbflow.sql.language.SQLite.select;
import static com.raizlabs.android.dbflow.sql.language.SQLite.selectCountOf;
import static junit.framework.Assert.assertEquals;

public class ConcurrentModelTest extends FlowTestCase {
    private static final long CONCURRENT_INSERT_COUNT = 10;
    private static final long CONCURRENT_INSERT_TIMEOUT = 60 * 1000;

    @Test
    public void testConcurrentInsert() throws InterruptedException {
        Delete.table(TestModel1.class);

        ExecutorService executorService = Executors.newFixedThreadPool(3);
        for (int i = 0; i < CONCURRENT_INSERT_COUNT; i++) {
            executorService.execute(new InsertRunnable());            // fails
            //executorService.execute(new PlainSqlInsertRunnable());    // passes
        }

        executorService.shutdown();
        executorService.awaitTermination(CONCURRENT_INSERT_TIMEOUT, TimeUnit.MILLISECONDS);

        long modelCount = selectCountOf().from(TestModel1.class).count();

        List<TestModel1> models = select().from(TestModel1.class).queryList();
        for (TestModel1 model : models) {
            System.out.println("Found: " + model.getName());
        }
        assertEquals(CONCURRENT_INSERT_COUNT, modelCount);
    }

    private static class InsertRunnable implements Runnable {
        private InsertRunnable() {
        }

        @Override
        public void run() {
            String uuid = UUID.randomUUID().toString();

            TestModel1 indexModel = new TestModel1();
            indexModel.setName(uuid);
            indexModel.insert();

            System.out.println("Inserting: " + indexModel.getName());

        }
    }

    private static class PlainSqlInsertRunnable implements Runnable {
        private PlainSqlInsertRunnable() {
        }

        @Override
        public void run() {
            String uuid = UUID.randomUUID().toString();

            Insert insert = SQLite.insert(TestModel1.class).orFail()
                    .values(uuid);

            FlowManager.getDatabase(TestDatabase.NAME).getWritableDatabase().execSQL(insert.getQuery());
        }
    }
}

@@ -469,31 +469,8 @@
 t;%0A%0A
-import java.util.List;%0A
 impo
@@ -488,16 +488,16 @@
 l.UUID;%0A
+
 import j
@@ -615,78 +615,8 @@
 t;%0A%0A
-import static com.raizlabs.android.dbflow.sql.language.SQLite.select;%0A
 impo
@@ -1559,201 +1559,8 @@
 t();
-%0A%0A        List%3CTestModel1%3E models = select().from(TestModel1.class).queryList();%0A        for (TestModel1 model : models) %7B%0A            System.out.println(%22Found: %22 + model.getName());%0A        %7D
 %0A   
@@ -1962,80 +1962,8 @@
 ();%0A
-%0A            System.out.println(%22Inserting: %22 + indexModel.getName());%0A%0A
     
@@ -2271,20 +2271,16 @@
 rFail()%0A
-    
         

clean up logs