package org.wikipedia.database;

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

import org.wikipedia.WikipediaApp;
import org.wikipedia.database.contract.AppContentProviderContract;
import org.wikipedia.util.log.L;

import java.util.Arrays;

public class AppContentProvider extends ContentProvider {
    private static final boolean LOG = false;

    @Override public boolean onCreate() {
        @SuppressWarnings("UnnecessaryLocalVariable") final boolean loaded = true;
        return loaded;
    }

    @Nullable @Override public Cursor query(@NonNull Uri uri, @Nullable String[] projection,
                                            @Nullable String selection,
                                            @Nullable String[] selectionArgs,
                                            @Nullable String sortOrder) {
        AppContentProviderEndpoint endpoint = AppContentProviderEndpoint.of(uri);

        SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
        builder.setTables(endpoint.tables());

        SQLiteDatabase db = readableDatabase();
        final String groupBy = null;
        final String having = null;

        if (LOG) {
            L.d("selectionArgs=" + Arrays.toString(selectionArgs));
            String sql = builder.buildQuery(projection, "(" + selection + ")", groupBy, having,
                    sortOrder, null);
            L.d("sql=" + sql);
        }

        Cursor cursor = builder.query(db, projection == null ? endpoint.projection() : projection,
                selection, selectionArgs, groupBy, having, sortOrder);

        if (cursor != null) {
            if (LOG) {
                L.d("count=" + cursor.getCount() + " columnNames=" + Arrays.toString(cursor.getColumnNames()));
            }
            cursor.setNotificationUri(getContentResolver(), uri);
        }
        return cursor;
    }

    @Nullable @Override public String getType(@NonNull Uri uri) {
        AppContentProviderEndpoint endpoint = AppContentProviderEndpoint.of(uri);
        return endpoint.type();
    }

    @Nullable @Override public Uri insert(@NonNull Uri uri, ContentValues values) {
        AppContentProviderEndpoint endpoint = AppContentProviderEndpoint.of(uri);

        SQLiteDatabase db = writableDatabase();
        final String nullColumnHack = null;
        db.replaceOrThrow(endpoint.tables(), nullColumnHack, values);

        notifyChange(uri);

        Uri itemUri = endpoint.itemUri(values);
        if (itemUri != null) {
            notifyChange(itemUri);
        }
        return itemUri;
    }

    @Override public int delete(@NonNull Uri uri, @Nullable String selection,
                                @Nullable String[] selectionArgs) {
        AppContentProviderEndpoint endpoint = AppContentProviderEndpoint.of(uri);

        SQLiteDatabase db = writableDatabase();
        int rows = db.delete(endpoint.tables(), selection, selectionArgs);

        notifyChange(uri);
        return rows;
    }

    @Override public int update(@NonNull Uri uri, @Nullable ContentValues values,
                                @Nullable String selection, @Nullable String[] selectionArgs) {
        AppContentProviderEndpoint endpoint = AppContentProviderEndpoint.of(uri);

        SQLiteDatabase db = writableDatabase();
        int rows = db.update(endpoint.tables(), values, selection, selectionArgs);

        notifyChange(uri);
        return rows;
    }

    private void notifyChange(@NonNull Uri uri) {
        boolean notify = uri.getBooleanQueryParameter(AppContentProviderContract.NOTIFY, true);
        if (getContentResolver() == null || !notify) {
            return;
        }
        getContentResolver().notifyChange(uri, null);
    }

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

    private SQLiteDatabase readableDatabase() {
        return WikipediaApp.getInstance().getDatabase().getReadableDatabase();
    }

    private SQLiteDatabase writableDatabase() {
        return WikipediaApp.getInstance().getDatabase().getWritableDatabase();
    }
}
