package com.cliqz.jsengine;

import android.content.Context;

import com.cliqz.jsengine.v8.JSApiException;
import com.cliqz.jsengine.v8.JSConsole;
import com.cliqz.jsengine.v8.Timers;
import com.cliqz.jsengine.v8.V8Engine;
import com.cliqz.jsengine.v8.api.ChromeUrlHandler;
import com.cliqz.jsengine.v8.api.Crypto;
import com.cliqz.jsengine.v8.api.FileIO;
import com.cliqz.jsengine.v8.api.HttpRequestPolicy;
import com.cliqz.jsengine.v8.api.SystemLoader;
import com.cliqz.jsengine.v8.api.WebRequest;

import org.json.JSONObject;

import java.io.IOException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;

public class Engine {

    final V8Engine jsengine;
    private final Context context;
    private final Set<Object> jsApis = new HashSet<>();
    final SystemLoader system;
    public final WebRequest webRequest;

    private static final String BUILD_PATH = "build";

    public Engine(final Context context, final boolean mobileDataEnabled) throws JSApiException {
        this.context = context.getApplicationContext();
        jsengine = new V8Engine();
        // load js APIs

        jsApis.add(new JSConsole(jsengine));
        jsApis.add(new Timers(jsengine));
        jsApis.add(new FileIO(jsengine, this.context));
        jsApis.add(new Crypto(jsengine));
        webRequest = new WebRequest(jsengine, this.context);
        system = new SystemLoader(jsengine, this.context, BUILD_PATH + "/modules");
        final HttpRequestPolicy policy = mobileDataEnabled ? HttpRequestPolicy.ALWAYS_ALLOWED : new HttpRequestPolicy.AllowOnWifi(this.context);
        jsApis.add(new ChromeUrlHandler(jsengine, policy, system));
    }

    public void startup(Map<String, Object> defaultPrefs) throws ExecutionException {
        try {
            // load config
            String config = system.readSourceFile(BUILD_PATH + "/config/cliqz.json");
            jsengine.executeScript("var __CONFIG__ = JSON.parse(\"" + config.replace("\"", "\\\"").replace("\n", "") + "\");");
            jsengine.executeScript("var __DEFAULTPREFS__ = JSON.parse(" + new JSONObject(defaultPrefs).toString() + ");");
            system.callVoidFunctionOnModule("platform/startup", "default");
        } catch(IOException e) {
            throw new ExecutionException(e);
        }
    }

    public void startup() throws ExecutionException {
        startup(new HashMap<String, Object>());
    }

    public void shutdown() {
        jsengine.shutdown();
    }

    public void setPref(String prefName, Object value) throws ExecutionException {
        system.callFunctionOnModuleDefault("core/utils", "setPref", prefName, value);
    }

    public Object getPref(String prefName) throws ExecutionException {
        return system.callFunctionOnModuleDefault("core/utils", "getPref");
    }


}

@@ -53,16 +53,41 @@
 Context;
+%0Aimport android.util.Log;
 %0A%0Aimport
@@ -744,16 +744,84 @@
 gine %7B%0A%0A
+    private final static String TAG = Engine.class.getSimpleName();%0A
     fina
@@ -1826,32 +1826,45 @@
   %7D%0A%0A    public 
+synchronized 
 void startup(Map
@@ -2572,32 +2572,554 @@
 ect%3E());%0A    %7D%0A%0A
+    /**%0A     * Run the normal startup asynchronously on a different thread%0A     * @param defaultPrefs%0A     */%0A    public void startupAsync(final Map%3CString, Object%3E defaultPrefs) %7B%0A        new Thread(new Runnable() %7B%0A            @Override%0A            public void run() %7B%0A                try %7B%0A                    Engine.this.startup(defaultPrefs);%0A                %7D catch (ExecutionException e) %7B%0A                    Log.e(Engine.TAG, %22Problem with startup%22, e);%0A                %7D%0A            %7D%0A        %7D).start();%0A    %7D%0A%0A
     public void 
@@ -3174,24 +3174,37 @@
 %0A    public 
+synchronized 
 void setPref
@@ -3367,16 +3367,29 @@
  public 
+synchronized 
 Object g

Add API for async startup.