/*
   forsuredbandroid, an android companion to the forsuredb project

   Copyright 2015 Ryan Scott

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.
 */
package com.fsryan.forsuredb;

import android.content.Context;
import android.net.Uri;

import com.fsryan.forsuredb.api.FSJoin;
import com.fsryan.forsuredb.api.FSProjection;
import com.fsryan.forsuredb.api.FSQueryable;
import com.fsryan.forsuredb.api.FSSelection;
import com.fsryan.forsuredb.api.Retriever;
import com.fsryan.forsuredb.api.sqlgeneration.Sql;
import com.fsryan.forsuredb.cursor.FSCursor;
import com.fsryan.forsuredb.provider.FSContentValues;
import com.google.common.collect.Lists;

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

/*package*/ class ContentProviderQueryable implements FSQueryable<Uri, FSContentValues> {

    private final Context appContext;
    private final Uri resource;

    public ContentProviderQueryable(Context appContext, Uri resource) {
        this.appContext = appContext;
        this.resource = resource;
    }

    @Override
    public Uri insert(FSContentValues cv) {
        return appContext.getContentResolver().insert(resource, cv.getContentValues());
    }

    @Override
    public int update(FSContentValues cv, FSSelection selection) {
        final String s = selection == null ? null : selection.where();
        final String[] sArgs = selection == null ? null : selection.replacements();
        return appContext.getContentResolver().update(resource, cv.getContentValues(), s, sArgs);
    }

    @Override
    public int delete(FSSelection selection) {
        final String s = selection == null ? null : selection.where();
        final String[] sArgs = selection == null ? null : selection.replacements();
        return appContext.getContentResolver().delete(resource, s, sArgs);
    }

    @Override
    public Retriever query(FSProjection projection, FSSelection selection, String sortOrder) {
        final String[] p = formatProjections(Lists.newArrayList(projection));
        final String s = selection == null ? null : selection.where();
        final String[] sArgs = selection == null ? null : selection.replacements();
        return new FSCursor(appContext.getContentResolver().query(resource, p, s, sArgs, sortOrder));
    }

    @Override
    public Retriever query(List<FSJoin> joins, List<FSProjection> projections, FSSelection selection, String sortOrder) {
        final String[] p = formatProjections(projections);
        final String s = selection == null ? null : selection.where();
        final String[] sArgs = selection == null ? null : selection.replacements();
        return new FSCursor(appContext.getContentResolver().query(resource, p, s, sArgs, sortOrder));
    }

    private String[] formatProjections(List<FSProjection> projections) {
        if (projections == null || projections.size() == 0) {
            return null;
        }
        List<String> formattedProjectionList = new ArrayList<>();
        for (FSProjection projection : projections) {
            appendProjectionToList(formattedProjectionList, projection);
        }
        return formattedProjectionList.toArray(new String[formattedProjectionList.size()]);
    }

    private void appendProjectionToList(List<String> listToAddTo, FSProjection projection) {
        if (projection == null || projection.columns() == null || projection.columns().length == 0) {
            return;
        }

//        The following code in SQLiteCursor.getColumnIndex forces us to disambiguate columns without using the table.column
//        notation
//        // Hack according to bug 903852
//        final int periodIndex = columnName.lastIndexOf('.');
//        if (periodIndex != -1) {
//            Exception e = new Exception();
//            Log.e(TAG, "requesting column name with table name -- " + columnName, e);
//            columnName = columnName.substring(periodIndex + 1);
//        }

        for (String column : projection.columns()) {
            final String unambiguousName = Sql.generator().unambiguousColumn(projection.tableName(), column);
            final String retrievalName = Sql.generator().unambiguousRetrievalColumn(projection.tableName(), column);
            listToAddTo.add(unambiguousName + " AS " + retrievalName);
        }
    }
}

@@ -1566,24 +1566,790 @@
 alues cv) %7B%0A
+        // SQLite either requires that there be a value for a column in an insert query or that the query be in the following%0A        // form: INSERT INTO table DEFAULT VALUES;%0A        // Since executing raw SQL on the SQLiteDatabase reference would achieve the desired result, but return void, we would%0A        // not get the Uri of the inserted resource back from the call.%0A        // This hack makes use of the fact that each forsuredb table has a 'deleted' column with a default value of 0. Since it%0A        // would have been 0 anyway, we can get away with this hack here and can avoid using the nullColumnHack encouraged by%0A        // the Android framework.%0A        if (cv.getContentValues().keySet().size() == 0) %7B%0A            cv.put(%22deleted%22, 0);%0A        %7D%0A
         retu

add deleted=0 to content values if FSContentValues passed to FSQueryable is empty