package com.drivemode.timberlorry.plug;

import android.accounts.Account;
import android.accounts.AccountManager;
import android.app.Application;
import android.content.ContentResolver;
import android.content.Context;
import android.support.annotation.NonNull;

import com.drivemode.timberlorry.buffer.AbstractBufferResolver;
import com.drivemode.timberlorry.internal.utils.Utils;
import com.drivemode.timberlorry.payload.Payload;
import com.drivemode.timberlorry.payload.Record;
import com.drivemode.timberlorry.payload.Serializer;

import java.util.ArrayList;
import java.util.List;

import io.realm.Realm;
import io.realm.RealmConfiguration;
import io.realm.RealmQuery;
import io.realm.RealmResults;

/**
 * @author KeishinYokomaku
 */
public class RealmBufferResolver extends AbstractBufferResolver {
    public static final String TAG = RealmBufferResolver.class.getSimpleName();
    private final RealmConfiguration realmConfig;

    public RealmBufferResolver(Application application, Account account, String name) {
        this(application, (AccountManager) application.getSystemService(Context.ACCOUNT_SERVICE), application.getContentResolver(), account, name);
    }

    protected RealmBufferResolver(Application application, @NonNull AccountManager accountManager, @NonNull ContentResolver resolver, Account account, String name) {
        super(accountManager, resolver, account);
        this.realmConfig = new RealmConfiguration.Builder(application.getApplicationContext())
                .name(name)
                .build();
    }

    @Override
    public void save(Serializer serializer, Payload payload) {
        Record record = new Record(payload.getClass(), serializer.serialize(payload));
        Realm realm = Realm.getInstance(realmConfig);
        realm.beginTransaction();
        RecordObject obj = realm.createObject(RecordObject.class);
        obj.setClassName(record.getClazz().getCanonicalName());
        obj.setBody(record.getBody());
        realm.commitTransaction();
    }

    @Override
    public void save(Serializer serializer, Payload... payloads) {
        for (Payload payload : payloads) {
            save(serializer, payload);
        }
    }

    @Override
    public List<Record> fetch() {
        List<Record> records = new ArrayList<>();
        Realm realm = Realm.getInstance(realmConfig);
        RealmQuery<RecordObject> query = realm.where(RecordObject.class);
        RealmResults<RecordObject> results = query.findAll();
        for(RecordObject obj : results) {
            records.add(new Record(Utils.forName(obj.getClassName()), obj.getBody()));
        }
        return records;
    }

    @Override
    public void remove(Record record) {
        Realm realm = Realm.getInstance(realmConfig);
        realm.beginTransaction();
        RealmQuery<RecordObject> query = realm.where(RecordObject.class);
        query.equalTo("className", record.getClazz().getCanonicalName())
                .equalTo("body", record.getBody()).findAll().remove(0);
        realm.commitTransaction();
    }

    @Override
    public void clear() {
        Realm realm = Realm.getInstance(realmConfig);
        realm.beginTransaction();
        realm.where(RecordObject.class).findAll().clear();
        realm.commitTransaction();
    }
}

@@ -1721,32 +1721,72 @@
    Realm realm =
+ null;%0A        try %7B%0A            realm =
  Realm.getInstan
@@ -1802,32 +1802,36 @@
 onfig);%0A        
+    
 realm.beginTrans
@@ -1832,32 +1832,36 @@
 nTransaction();%0A
+    
         RecordOb
@@ -1915,24 +1915,28 @@
 s);%0A        
+    
 obj.setClass
@@ -1983,24 +1983,28 @@
 ));%0A        
+    
 obj.setBody(
@@ -2022,32 +2022,36 @@
 ody());%0A        
+ 
+   
 realm.commitTran
@@ -2053,32 +2053,124 @@
 tTransaction();%0A
+        %7D finally %7B%0A            if (realm != null)%0A                realm.close();%0A        %7D%0A
     %7D%0A%0A    @Over
@@ -2451,32 +2451,72 @@
    Realm realm =
+ null;%0A        try %7B%0A            realm =
  Realm.getInstan
@@ -2524,32 +2524,36 @@
 e(realmConfig);%0A
+    
         RealmQue
@@ -2602,32 +2602,36 @@
 dObject.class);%0A
+    
         RealmRes
@@ -2684,19 +2684,24 @@
         
+    
 for
+ 
 (RecordO
@@ -2719,24 +2719,28 @@
  results) %7B%0A
+    
             
@@ -2818,26 +2818,34 @@
 ));%0A        
-%7D%0A
+    %7D%0A    
         retu
@@ -2856,16 +2856,108 @@
 ecords;%0A
+        %7D finally %7B%0A            if (realm != null)%0A                realm.close();%0A        %7D%0A
     %7D%0A%0A 
@@ -3022,32 +3022,72 @@
    Realm realm =
+ null;%0A        try %7B%0A            realm =
  Realm.getInstan
@@ -3103,32 +3103,36 @@
 onfig);%0A        
+  
+  
 realm.beginTrans
@@ -3133,32 +3133,36 @@
 nTransaction();%0A
+    
         RealmQue
@@ -3227,16 +3227,20 @@
         
+   
+ 
 query.eq
@@ -3292,24 +3292,28 @@
 icalName())%0A
+    
             
@@ -3372,32 +3372,36 @@
 ove(0);%0A        
+    
 realm.commitTran
@@ -3407,24 +3407,116 @@
 nsaction();%0A
+        %7D finally %7B%0A            if (realm != null)%0A                realm.close();%0A        %7D%0A
     %7D%0A%0A    @
@@ -3563,32 +3563,72 @@
    Realm realm =
+ null;%0A        try %7B%0A            realm =
  Realm.getInstan
@@ -3644,32 +3644,36 @@
 onfig);%0A        
+ 
+   
 realm.beginTrans
@@ -3674,32 +3674,36 @@
 nTransaction();%0A
+    
         realm.wh
@@ -3745,32 +3745,36 @@
 lear();%0A        
+  
+  
 realm.commitTran
@@ -3780,20 +3780,112 @@
 nsaction();%0A
+        %7D finally %7B%0A            if (realm != null)%0A                realm.close();%0A        %7D%0A
     %7D%0A%7D%0A

Fix #2: Close realm instance