package org.commcare.test.utilities;

import org.commcare.modern.session.SessionWrapper;
import org.commcare.core.parse.ParseUtils;
import org.commcare.util.CommCareConfigEngine;
import org.commcare.util.mocks.MockUserDataSandbox;
import org.javarosa.core.model.User;
import org.javarosa.core.services.storage.IStorageIterator;
import org.javarosa.core.util.externalizable.LivePrototypeFactory;

/**
 * A mock app is a quick test wrapper that makes it easy to start playing with a live instance
 * of a CommCare app including the session and user data that goes along with it.
 *
 * To use this class, make a copy of the /template/ app in the test resources and extend the
 * config and data in that copy, then pass its resource path to the constructor.
 *
 * Created by ctsims on 8/14/2015.
 */
public class MockApp {
    private final SessionWrapper mSessionWrapper;

    /**
     * Creates and initializes a mockapp that is located at the provided Java Resource path.
     *
     * @param resourcePath The resource path to a an app template. Needs to contain a leading and
     *                     trailing slash, like /path/app/
     */
    public MockApp(String resourcePath) throws Exception {
        if(!(resourcePath.startsWith("/") && resourcePath.endsWith("/"))) {
            throw new IllegalArgumentException("Invalid resource path for a mock app " + resourcePath);
        }
        LivePrototypeFactory mPrototypeFactory = setupStaticStorage();
        MockUserDataSandbox mSandbox = new MockUserDataSandbox(mPrototypeFactory);
        CommCareConfigEngine mEngine = new CommCareConfigEngine(mPrototypeFactory);

        mEngine.installAppFromReference("jr://resource" + resourcePath + "profile.ccpr");
        mEngine.initEnvironment();
        ParseUtils.parseIntoSandbox(this.getClass().getResourceAsStream(resourcePath + "user_restore.xml"), mSandbox);

        //If we parsed in a user, arbitrarily log one in.
        for(IStorageIterator<User> iterator = mSandbox.getUserStorage().iterate(); iterator.hasMore();) {
            mSandbox.setLoggedInUser(iterator.nextRecord());
            break;
        }

        mSessionWrapper = new SessionWrapper(mEngine.getPlatform(), mSandbox);
    }


    private static LivePrototypeFactory setupStaticStorage() {
        return new LivePrototypeFactory();
    }

    public SessionWrapper getSession() {
        return mSessionWrapper;
    }

}

@@ -224,16 +224,98 @@
 andbox;%0A
+import org.javarosa.core.model.FormDef;%0Aimport org.javarosa.core.model.FormIndex;%0A
 import o
@@ -403,16 +403,61 @@
 erator;%0A
+import org.javarosa.core.test.FormParseInit;%0A
 import o
@@ -514,16 +514,66 @@
 Factory;
+%0Aimport org.javarosa.form.api.FormEntryController;
 %0A%0A/**%0A *
@@ -1038,16 +1038,51 @@
 Wrapper;
+%0A    private final String APP_BASE;
 %0A%0A    /*
@@ -1597,16 +1597,49 @@
       %7D%0A
+        APP_BASE = resourcePath;%0A
         
@@ -1927,28 +1927,24 @@
 urce%22 + 
-resourcePath
+APP_BASE
  + %22prof
@@ -2062,28 +2062,24 @@
 sStream(
-resourcePath
+APP_BASE
  + %22user
@@ -2176,175 +2176,432 @@
     
-for(IStorageIterator%3CUser%3E iterator = mSandbox.getUserStorage().iterate(); iterator.hasMore();) %7B%0A            mSandbox.setLoggedInUser(iterator.nextRecord
+mSandbox.setLoggedInUser(mSandbox.getUserStorage().read(0));%0A%0A        mSessionWrapper = new SessionWrapper(mEngine.getPlatform(), mSandbox);%0A    %7D%0A%0A    public FormParseInit loadAndInitForm(String formFileInApp) %7B%0A        FormParseInit fpi = new FormParseInit(APP_BASE + formFileInApp);%0A        FormEntryController fec = fpi.getFormEntryController();%0A        fec.jumpToIndex(FormIndex.createBeginningOfFormIndex
 ());%0A
+%0A
         
     
@@ -2600,107 +2600,207 @@
     
-    break;%0A        %7D%0A%0A        mSessionWrapper = new SessionWrapper(mEngine.getPlatform(), mSandbox)
+FormDef fd = fpi.getFormDef();%0A        // run initialization to ensure xforms-ready event and binds are%0A        // triggered.%0A        fd.initialize(true, mSessionWrapper.getIIF());%0A        return fpi
 ;%0A  

Allow MockApp to load form with instances properly initialized