package com.raizlabs.android.dbflow.structure;

import android.support.annotation.NonNull;

import com.raizlabs.android.dbflow.sql.BaseAsyncObject;
import com.raizlabs.android.dbflow.structure.database.transaction.DefaultTransactionQueue;
import com.raizlabs.android.dbflow.structure.database.transaction.ProcessModelTransaction;
import com.raizlabs.android.dbflow.structure.database.transaction.Transaction;

import java.lang.ref.WeakReference;

/**
 * Description: Called from a {@link BaseModel}, this places the current {@link Model} interaction on the background.
 */
public class AsyncModel<TModel extends Model> extends BaseAsyncObject<AsyncModel<TModel>> implements Model {

    /**
     * Listens for when this {@link Model} modification completes.
     */
    public interface OnModelChangedListener {

        /**
         * Called when the change finishes on the {@link DefaultTransactionQueue}. This method is called on the UI thread.
         */
        void onModelChanged(Model model);
    }

    private final TModel model;
    private transient WeakReference<OnModelChangedListener> onModelChangedListener;


    public AsyncModel(@NonNull TModel referenceModel) {
        super(referenceModel.getClass());
        model = referenceModel;
    }

    /**
     * Call before {@link #save()}, {@link #delete()}, {@link #update()}, or {@link #insert()} since post
     * call to those the listener is nulled out.
     *
     * @param onModelChangedListener The listener to use for a corresponding call to a method.
     */
    public AsyncModel<TModel> withListener(OnModelChangedListener onModelChangedListener) {
        this.onModelChangedListener = new WeakReference<>(onModelChangedListener);
        return this;
    }


    @Override
    public void save() {
        executeTransaction(new ProcessModelTransaction.Builder<>(
                new ProcessModelTransaction.ProcessModel<TModel>() {
                    @Override
                    public void processModel(TModel model) {
                        model.save();
                    }
                }).build());
    }

    @Override
    public void delete() {
        executeTransaction(new ProcessModelTransaction.Builder<>(
                new ProcessModelTransaction.ProcessModel<TModel>() {
                    @Override
                    public void processModel(TModel model) {
                        model.delete();
                    }
                }).build());
    }

    @Override
    public void update() {
        executeTransaction(new ProcessModelTransaction.Builder<>(
                new ProcessModelTransaction.ProcessModel<TModel>() {
                    @Override
                    public void processModel(TModel model) {
                        model.update();
                    }
                }).build());
    }

    @Override
    public void insert() {
        executeTransaction(new ProcessModelTransaction.Builder<>(
                new ProcessModelTransaction.ProcessModel<TModel>() {
                    @Override
                    public void processModel(TModel model) {
                        model.insert();
                    }
                }).build());
    }

    @Override
    public boolean exists() {
        return model.exists();
    }

    @Override
    protected void onSuccess(Transaction transaction) {
        if (onModelChangedListener != null && onModelChangedListener.get() != null) {
            onModelChangedListener.get().onModelChanged(model);
        }
    }
}

@@ -2070,32 +2070,43 @@
              %7D).
+add(model).
 build());%0A    %7D%0A
@@ -2091,32 +2091,32 @@
 odel).build());%0A
-
     %7D%0A%0A    @Over
@@ -2446,32 +2446,43 @@
              %7D).
+add(model).
 build());%0A    %7D%0A
@@ -2822,32 +2822,43 @@
              %7D).
+add(model).
 build());%0A    %7D%0A
@@ -3179,32 +3179,32 @@
               %7D%0A
-
                 
@@ -3206,16 +3206,27 @@
      %7D).
+add(model).
 build())

fix issue where model not added to async