package org.commcare.models.database;

import net.sqlcipher.Cursor;
import net.sqlcipher.database.SQLiteDatabase;

import org.commcare.CommCareApplication;
import org.commcare.cases.ledger.Ledger;
import org.commcare.cases.model.Case;
import org.commcare.cases.model.StorageBackedModel;
import org.commcare.core.interfaces.UserSandbox;
import org.commcare.android.database.user.models.ACase;
import org.commcare.models.database.user.DatabaseUserOpenHelper;
import org.commcare.modern.database.TableBuilder;
import org.commcare.modern.util.Pair;
import org.commcare.utils.SessionUnavailableException;
import org.javarosa.core.model.User;
import org.javarosa.core.model.instance.FormInstance;
import org.javarosa.core.services.storage.IStorageUtilityIndexed;
import org.javarosa.core.services.storage.Persistable;

/**
 * Basically just a useful abstraction that allows us to use an Android
 * CommCareApplication as a UserDataInterface
 *
 * Created by wpride1 on 8/11/15.
 */
public class AndroidSandbox extends UserSandbox {

    private final CommCareApplication app;

    public AndroidSandbox(CommCareApplication app) {
        this.app = app;
    }

    @Override
    public IStorageUtilityIndexed<Case> getCaseStorage() {
        return app.getUserStorage(ACase.STORAGE_KEY, ACase.class);
    }

    @Override
    public IStorageUtilityIndexed<Ledger> getLedgerStorage() {
        return app.getUserStorage(Ledger.STORAGE_KEY, Ledger.class);
    }

    @Override
    public IStorageUtilityIndexed<User> getUserStorage() {
        return app.getUserStorage("USER", User.class);
    }

    @Override
    public IStorageUtilityIndexed<StorageBackedModel> getFlatFixtureStorage(String fixtureName,
                                                                            Persistable exampleEntry) {
        String tableName = StorageBackedModel.STORAGE_KEY + TableBuilder.cleanTableName(fixtureName);
        if (exampleEntry != null) {
            DatabaseUserOpenHelper.buildTable(app.getUserDbHandle(), tableName, exampleEntry);
        }
        return app.getUserStorage(tableName, StorageBackedModel.class);
    }

    @Override
    public Pair<String, String> getFlatFixturePathBases(String fixtureName) {
        SQLiteDatabase db = app.getUserDbHandle();
        Cursor c = db.query(DbUtil.FLAT_FIXTURE_INDEX_TABLE,
                new String[]{DbUtil.FLAT_FIXTURE_INDEX_COL_BASE, DbUtil.FLAT_FIXTURE_INDEX_COL_CHILD},
                DbUtil.FLAT_FIXTURE_INDEX_COL_NAME + "=?", new String[]{fixtureName}, null, null, null);
        try {
            if (c.getCount() == 0) {
                throw new RuntimeException("no entry for " + fixtureName);
            }
            c.moveToFirst();
            return Pair.create(
                    c.getString(c.getColumnIndexOrThrow(DbUtil.FLAT_FIXTURE_INDEX_COL_BASE)),
                    c.getString(c.getColumnIndexOrThrow(DbUtil.FLAT_FIXTURE_INDEX_COL_CHILD)));
        } finally {
            c.close();
        }
    }

    @Override
    public void setFlatFixturePathBases(String fixtureName, String baseName, String childName) {
        SQLiteDatabase db = app.getUserDbHandle();
        try {
            db.beginTransaction();
            long ret = db.insertOrThrow(DbUtil.FLAT_FIXTURE_INDEX_TABLE,
                    DatabaseHelper.DATA_COL, helper.getContentValues(e));

            if (ret > Integer.MAX_VALUE) {
                throw new RuntimeException("Waaaaaaaaaay too many values");
            }

            i = (int)ret;

            db.setTransactionSuccessful();
        } finally {
            db.endTransaction();
        }
        Cursor c = db.query(
                new String[]{DbUtil.FLAT_FIXTURE_INDEX_COL_BASE, DbUtil.FLAT_FIXTURE_INDEX_COL_CHILD},
                DbUtil.FLAT_FIXTURE_INDEX_COL_NAME + "=?", new String[]{fixtureName}, null, null, null);
        try {
            if (c.getCount() == 0) {
                throw new RuntimeException("no entry for " + fixtureName);
            }
            c.moveToFirst();
            return Pair.create(
                    c.getString(c.getColumnIndexOrThrow(DbUtil.FLAT_FIXTURE_INDEX_COL_BASE)),
                    c.getString(c.getColumnIndexOrThrow(DbUtil.FLAT_FIXTURE_INDEX_COL_CHILD)));
        } finally {
            c.close();
        }
    }

    @Override
    public IStorageUtilityIndexed<FormInstance> getUserFixtureStorage() {
        return app.getFileBackedUserStorage("fixture", FormInstance.class);
    }

    @Override
    public IStorageUtilityIndexed<FormInstance> getAppFixtureStorage() {
        return app.getFileBackedAppStorage("fixture", FormInstance.class);
    }

    @Override
    public User getLoggedInUser() {
        try {
            return app.getSession().getLoggedInUser();
        } catch (SessionUnavailableException e) {
            return null;
        }
    }

    @Override
    public void setLoggedInUser(User user) {

    }
}

@@ -28,24 +28,63 @@
 .database;%0A%0A
+import android.content.ContentValues;%0A%0A
 import net.s
@@ -3175,32 +3175,316 @@
 UserDbHandle();%0A
+        ContentValues contentValues = new ContentValues();%0A        contentValues.put(DbUtil.FLAT_FIXTURE_INDEX_COL_BASE, baseName);%0A        contentValues.put(DbUtil.FLAT_FIXTURE_INDEX_COL_CHILD, childName);%0A        contentValues.put(DbUtil.FLAT_FIXTURE_INDEX_COL_NAME, fixtureName);%0A%0A
         try %7B%0A  
@@ -3473,32 +3473,32 @@
 %0A%0A        try %7B%0A
-
             db.b
@@ -3508,32 +3508,33 @@
 nTransaction();%0A
+%0A
             long
@@ -3615,43 +3615,64 @@
    D
-atabaseHelper.DATA_COL, helper.getC
+bUtil.FLAT_FIXTURE_INDEX_COL_BASE,%0A                    c
 onte
@@ -3683,11 +3683,8 @@
 lues
-(e)
 );%0A%0A
@@ -3821,35 +3821,8 @@
  %7D%0A%0A
-            i = (int)ret;%0A%0A
     
@@ -3872,32 +3872,32 @@
     %7D finally %7B%0A
+
             db.e
@@ -3927,689 +3927,8 @@
   %7D%0A
-        Cursor c = db.query(%0A                new String%5B%5D%7BDbUtil.FLAT_FIXTURE_INDEX_COL_BASE, DbUtil.FLAT_FIXTURE_INDEX_COL_CHILD%7D,%0A                DbUtil.FLAT_FIXTURE_INDEX_COL_NAME + %22=?%22, new String%5B%5D%7BfixtureName%7D, null, null, null);%0A        try %7B%0A            if (c.getCount() == 0) %7B%0A                throw new RuntimeException(%22no entry for %22 + fixtureName);%0A            %7D%0A            c.moveToFirst();%0A            return Pair.create(%0A                    c.getString(c.getColumnIndexOrThrow(DbUtil.FLAT_FIXTURE_INDEX_COL_BASE)),%0A                    c.getString(c.getColumnIndexOrThrow(DbUtil.FLAT_FIXTURE_INDEX_COL_CHILD)));%0A        %7D finally %7B%0A            c.close();%0A        %7D%0A
     

implement flat fixture insert