package com.raizlabs.android.dbflow.sql.saveable;

import android.content.ContentValues;

import com.raizlabs.android.dbflow.SQLiteCompatibilityUtils;
import com.raizlabs.android.dbflow.annotation.ConflictAction;
import com.raizlabs.android.dbflow.config.FlowManager;
import com.raizlabs.android.dbflow.sql.SqlUtils;
import com.raizlabs.android.dbflow.sql.language.Delete;
import com.raizlabs.android.dbflow.sql.language.SQLite;
import com.raizlabs.android.dbflow.structure.BaseModel;
import com.raizlabs.android.dbflow.structure.InternalAdapter;
import com.raizlabs.android.dbflow.structure.Model;
import com.raizlabs.android.dbflow.structure.ModelAdapter;
import com.raizlabs.android.dbflow.structure.RetrievalAdapter;
import com.raizlabs.android.dbflow.structure.database.DatabaseStatement;
import com.raizlabs.android.dbflow.structure.database.DatabaseWrapper;

/**
 * Description: Defines how models get saved into the DB. It will bind values to {@link android.content.ContentValues} for
 * an update, execute a {@link DatabaseStatement}, or delete an object via the {@link Delete} wrapper.
 */
public class ModelSaver<ModelClass extends Model, TableClass extends Model, AdapterClass extends RetrievalAdapter & InternalAdapter> {

    private final ModelAdapter<ModelClass> modelAdapter;
    private final AdapterClass adapter;

    public ModelSaver(ModelAdapter<ModelClass> modelAdapter, AdapterClass adapter) {
        this.modelAdapter = modelAdapter;
        this.adapter = adapter;
    }

    @SuppressWarnings("unchecked")
    public void save(TableClass model) {
        if (model == null) {
            throw new IllegalArgumentException("Model from " + modelAdapter.getModelClass() + " was null");
        }

        boolean exists = adapter.exists(model);

        if (exists) {
            exists = update(model);
        }

        if (!exists) {
            insert(model);
        }

        SqlUtils.notifyModelChanged(model, adapter, modelAdapter, BaseModel.Action.SAVE);
    }

    @SuppressWarnings("unchecked")
    public boolean update(TableClass model) {
        DatabaseWrapper db = FlowManager.getDatabaseForTable(modelAdapter.getModelClass()).getWritableDatabase();
        ContentValues contentValues = new ContentValues();
        adapter.bindToContentValues(contentValues, model);
        boolean successful = (SQLiteCompatibilityUtils.updateWithOnConflict(db, modelAdapter.getTableName(), contentValues,
            adapter.getPrimaryConditionClause(model).getQuery(), null,
            ConflictAction.getSQLiteDatabaseAlgorithmInt(
                modelAdapter.getUpdateOnConflictAction())) !=
            0);
        if (successful) {
            SqlUtils.notifyModelChanged(model, adapter, modelAdapter, BaseModel.Action.UPDATE);
        }
        return successful;
    }

    @SuppressWarnings("unchecked")
    public long insert(TableClass model) {
        DatabaseStatement insertStatement = modelAdapter.getInsertStatement();
        adapter.bindToInsertStatement(insertStatement, model);
        long id = insertStatement.executeInsert();
        adapter.updateAutoIncrement(model, id);
        SqlUtils.notifyModelChanged(model, adapter, modelAdapter, BaseModel.Action.INSERT);
        return id;
    }

    @SuppressWarnings("unchecked")
    public void delete(TableClass model) {
        SQLite.delete((Class<TableClass>) adapter.getModelClass()).where(
            adapter.getPrimaryConditionClause(model)).execute();
        SqlUtils.notifyModelChanged(model, adapter, modelAdapter, BaseModel.Action.DELETE);
        adapter.updateAutoIncrement(model, 0);
    }
}

@@ -2335,17 +2335,16 @@
 ssful = 
-(
 SQLiteCo
@@ -2384,16 +2384,28 @@
 lict(db,
+%0A           
  modelAd
@@ -2440,28 +2440,16 @@
 tValues,
-%0A           
  adapter
@@ -2561,25 +2561,8 @@
 Int(
-%0A                
 mode
@@ -2606,23 +2606,10 @@
 ) !=
-%0A           
  0
-)
 ;%0A  
@@ -3255,20 +3255,23 @@
  public 
-void
+boolean
  delete(
@@ -3297,16 +3297,37 @@
 %0A       
+ boolean successful =
  SQLite.
@@ -3443,19 +3443,52 @@
 l)).
-execute();%0A
+count() != 0;%0A        if (successful) %7B%0A    
     
@@ -3571,24 +3571,34 @@
 on.DELETE);%0A
+        %7D%0A
         adap
@@ -3632,16 +3632,43 @@
 el, 0);%0A
+        return successful;%0A
     %7D%0A%7D%0A

change return value on modelsaver.