package eu.kanade.mangafeed.data.managers;

import com.pushtorefresh.storio.sqlite.StorIOSQLite;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResult;
import com.pushtorefresh.storio.sqlite.operations.delete.DeleteResults;
import com.pushtorefresh.storio.sqlite.operations.get.PreparedGetListOfObjects;
import com.pushtorefresh.storio.sqlite.operations.put.PutResult;
import com.pushtorefresh.storio.sqlite.operations.put.PutResults;
import com.pushtorefresh.storio.sqlite.queries.Query;

import java.util.List;

import eu.kanade.mangafeed.data.models.Chapter;
import eu.kanade.mangafeed.data.models.Manga;
import eu.kanade.mangafeed.data.tables.ChaptersTable;
import rx.Observable;

public class ChapterManager extends BaseManager {

    public ChapterManager(StorIOSQLite db) {
        super(db);
    }

    private PreparedGetListOfObjects<Chapter> prepareGet(Manga manga) {
        return db.get()
                .listOfObjects(Chapter.class)
                .withQuery(Query.builder()
                        .table(ChaptersTable.TABLE)
                        .where(ChaptersTable.COLUMN_MANGA_ID + "=?")
                        .whereArgs(manga.id)
                        .build())
                .prepare();
    }

    public Observable<List<Chapter>> get(Manga manga) {
        return prepareGet(manga).createObservable();
    }

    public Observable<PutResult> insert(Chapter chapter) {
        return db.put()
                .object(chapter)
                .prepare()
                .createObservable();
    }

    public Observable<PutResults<Chapter>> insert(List<Chapter> chapters) {
        return db.put()
                .objects(chapters)
                .prepare()
                .createObservable();
    }

    // Add new chapters or delete if the source deletes them
    public Observable insertOrRemove(Manga manga, List<Chapter> chapters) {
        // I don't know a better approach
        return Observable.create(subscriber -> {
            List<Chapter> dbGet = prepareGet(manga).executeAsBlocking();

            Observable.just(dbGet)
                    .doOnNext(dbChapters -> {
                        Observable.from(chapters)
                                .filter(c -> !dbChapters.contains(c))
                                .toList()
                                .subscribe(newChapters -> {
                                    if (newChapters.size() > 0)
                                        insert(newChapters).subscribe();
                                });
                    })
                    .flatMap(Observable::from)
                    .filter(c -> !chapters.contains(c))
                    .toList()
                    .subscribe(removedChapters -> {
                        if (removedChapters.size() > 0)
                            delete(removedChapters).subscribe();
                        subscriber.onCompleted();
                    });

        });

    }

    public void createDummyChapters() {
        Chapter c;

        for (int i = 1; i < 100; i++) {
            c = new Chapter();
            c.manga_id = 1L;
            c.name = "Chapter " + i;
            c.url = "http://example.com/1";
            insert(c).subscribe();
        }

    }

    public Observable<DeleteResults<Chapter>> delete(List<Chapter> chapters) {
        return db.delete()
                .objects(chapters)
                .prepare()
                .createObservable();
    }

    public Observable<DeleteResult> delete(Chapter chapter) {
        return db.delete()
                .object(chapter)
                .prepare()
                .createObservable();
    }
}

@@ -1924,16 +1924,48 @@
 pproach%0A
+        // TODO Fix this method%0A
         
@@ -2033,19 +2033,24 @@
 pter%3E db
-Get
+Chapters
  = prepa
@@ -2110,71 +2110,41 @@
 able
-.just(dbGet)%0A                    .doOnNext(dbChapters -%3E %7B%0A    
+%3CList%3CChapter%3E%3E newChaptersObs =%0A
     
@@ -2201,36 +2201,24 @@
             
-   
-         
 .filter(c -%3E
@@ -2267,286 +2267,83 @@
     
-            .toList()%0A                                .subscribe(newChapters -%3E %7B%0A                                    if (newChapters.size() %3E 0)%0A                                        insert(newChapters).subscribe();%0A                                %7D);%0A                    %7D)%0A
+.toList();%0A%0A            Observable%3CList%3CChapter%3E%3E deletedChaptersObs =%0A    
     
@@ -2358,21 +2358,8 @@
     
-    .flatMap(
 Obse
@@ -2368,14 +2368,24 @@
 able
-::
+.
 from
+(dbChapters
 )%0A  
@@ -2467,16 +2467,18 @@
 toList()
+;%0A
 %0A       
@@ -2486,32 +2486,98 @@
     
-        .subscribe(remov
+Observable.zip(newChaptersObs, deletedChaptersObs,%0A                    (newChapters, delet
 edCh
@@ -2582,16 +2582,17 @@
 Chapters
+)
  -%3E %7B%0A  
@@ -2618,26 +2618,25 @@
    i
-f (removed
+nsert(new
 Chapters
 .siz
@@ -2635,25 +2635,23 @@
 ters
+)
 .s
-ize() %3E 0)%0A    
+ubscribe();%0A
     
@@ -2681,13 +2681,13 @@
 ete(
-remov
+delet
 edCh
@@ -2773,28 +2773,76 @@
             
-%7D);%0A
+    return null;%0A                    %7D).subscribe();
 %0A        %7D);

Insert or remove method (meh)