package de.wackernagel.android.sidekick.frameworks.contentproviderprocessor;

import android.content.ContentProvider;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteOpenHelper;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

public abstract class AbstractContentProvider extends ContentProvider {

    private SQLiteOpenHelper dbHelper;
    private ContentProviderProcessor[] processors;

    @Override
    public boolean onCreate() {
        dbHelper = onCreateSQLiteOpenHelper();
        processors = onCreateContentProviderProcessors();
        return true;
    }

    @NonNull
    public abstract SQLiteOpenHelper onCreateSQLiteOpenHelper();

    @NonNull
    public abstract ContentProviderProcessor[] onCreateContentProviderProcessors();

    @Override
    public String getType(@NonNull Uri uri) {
        final ContentProviderProcessor processor = findProcessor(uri);
        if (processor == null) {
            return null;
        }
        return processor.getType(uri);
    }

    @Override
    public Cursor query(@NonNull Uri uri, @Nullable String[] projection, @Nullable String selection, @Nullable String[] selectionArgs, @Nullable String sortOrder) {
        final ContentProviderProcessor processor = findProcessor(uri);
        if (processor == null) {
            throw new IllegalArgumentException("Unkown URI: " + uri);
        }
        return processor.query(dbHelper.getWritableDatabase(), getContentResolver(), uri, projection, selection, selectionArgs, sortOrder);
    }

    @Override
    public Uri insert(@NonNull Uri uri, @Nullable ContentValues values) {
        final ContentProviderProcessor processor = findProcessor(uri);
        if (processor == null) {
            throw new IllegalArgumentException("Unkown URI: " + uri);
        }
        return processor.insert(dbHelper.getWritableDatabase(), getContentResolver(), uri, values);
    }

    @Override
    public int update(@NonNull Uri uri, @Nullable ContentValues values, @Nullable String selection, @Nullable String[] selectionArgs) {
        final ContentProviderProcessor processor = findProcessor(uri);
        if (processor == null) {
            throw new IllegalArgumentException("Unkown URI: " + uri);
        }
        return processor.update(dbHelper.getWritableDatabase(), getContentResolver(), uri, values, selection, selectionArgs);
    }

    @Override
    public int delete(@NonNull Uri uri, @Nullable String selection, @Nullable String[] selectionArgs) {
        final ContentProviderProcessor processor = findProcessor(uri);
        if (processor == null) {
            throw new IllegalArgumentException("Unkown URI: " + uri);
        }
        return processor.delete(dbHelper.getWritableDatabase(), getContentResolver(), uri, selection, selectionArgs);
    }

    @Nullable
    private ContentProviderProcessor findProcessor(@NonNull Uri uri) {
        final int size = processors.length;
        for( int index = 0; index < size; index++ ) {
            if( processors[index].canProcess( uri ) ) {
                return processors[index];
            }
        }
        return null;
    }

    @Nullable
    private ContentResolver getContentResolver() {
        final Context context = getContext();
        return context != null ? context.getContentResolver() : null;
    }

    @NonNull
    public SQLiteOpenHelper getSQLiteOpenHelper() {
        return dbHelper;
    }

    @NonNull
    public ContentProviderProcessor[] getProcessors() {
        return processors;
    }
}
@@ -145,118 +145,314 @@
 tent
-Resolver;%0Aimport android.content.ContentValues;%0Aimport android.content.Context;%0Aimport android.database.Cursor
+ProviderOperation;%0Aimport android.content.ContentProviderResult;%0Aimport android.content.ContentResolver;%0Aimport android.content.ContentValues;%0Aimport android.content.Context;%0Aimport android.content.OperationApplicationException;%0Aimport android.database.Cursor;%0Aimport android.database.sqlite.SQLiteDatabase
 ;%0Aim
@@ -610,16 +610,45 @@
 lable;%0A%0A
+import java.util.ArrayList;%0A%0A
 public a
@@ -3179,32 +3179,1076 @@
 onArgs);%0A    %7D%0A%0A
+    /**%0A     * Apply the given set of %7B@link ContentProviderOperation%7D, executing inside%0A     * a %7B@link SQLiteDatabase%7D transaction. All changes will be rolled back if%0A     * any single one fails.%0A     */%0A    @NonNull%0A    @Override%0A    public ContentProviderResult%5B%5D applyBatch( @NonNull ArrayList%3CContentProviderOperation%3E operations ) throws OperationApplicationException %7B%0A        if( operations.isEmpty() ) %7B%0A            return new ContentProviderResult%5B0%5D;%0A        %7D%0A%0A        final SQLiteDatabase db = dbHelper.getWritableDatabase();%0A        db.beginTransaction();%0A        try %7B%0A            final int numOperations = operations.size();%0A            final ContentProviderResult%5B%5D results = new ContentProviderResult%5BnumOperations%5D;%0A            for( int index = 0; index %3C numOperations; index++ ) %7B%0A                results%5Bindex%5D = operations.get(index).apply( this, results, index );%0A            %7D%0A            db.setTransactionSuccessful();%0A            return results;%0A        %7D finally %7B%0A            db.endTransaction();%0A        %7D%0A    %7D%0A%0A
     @Nullable%0A  

add Transactions to bulky ContentProvider operations