/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership.  The ASF licenses this file
 * to you 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.taobao.weex.bridge;

import android.text.TextUtils;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.WXSDKInstance;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.common.IWXBridge;
import com.taobao.weex.utils.WXLogUtils;

/**
 * Communication interface for Java code and JavaScript code.
 */
class WXBridge implements IWXBridge {

  public static final String TAG = "WXBridge";

  public static final boolean MULTIPROCESS = true;

  /**
   * Init JSFrameWork
   *
   * @param framework assets/main.js
   */
  public native int initFramework(String framework, WXParams params);

  /**
   * Init JSFrameWork
   *
   * @param framework assets/main.js
   */
  public native int initFramework(String framework, WXParams params, String cacheDir, boolean pieSupport);


  /**
   * Execute JavaScript function
   *
   * @param instanceId
   * @param namespace  default global
   * @param function   function string name
   * @param args       WXJSObject array
   */
  public native int execJS(String instanceId, String namespace, String function, WXJSObject[] args);


  /**
   * register Weex Service
   *
   * @param javascript  code
   */
  public native int execJSService(String javascript);

  /**
   * Take v8's heap snapshot
   * @param filename the name of the file to be written.
   */
  public native void takeHeapSnapshot(String filename);


  public int initFrameworkEnv(String framework, WXParams params, String cacheDir, boolean pieSupport){
    if (MULTIPROCESS) {
      return initFramework(framework, params, cacheDir, pieSupport);
    } else {
      return  initFramework(framework, params);
    }
  }
  /**
   * JavaScript uses this methods to call Android code
   *
   * @param instanceId
   * @param tasks
   * @param callback
   */

  public int callNative(String instanceId, byte [] tasks, String callback) {
     return callNative(instanceId,new String(tasks),callback);
  }

  public int callNative(String instanceId, String tasks, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callNative(instanceId, tasks, callback);
    }catch (Throwable e){
      //catch everything during call native.
      // if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callNative throw exception:"+e.getMessage());
      // }
    }

    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    if(WXEnvironment.isApkDebugable()){
      if(errorCode == IWXBridge.DESTROY_INSTANCE){
        WXLogUtils.w("destroyInstance :"+instanceId+" JSF must stop callNative");
      }
    }
    return errorCode;
  }
  public int callAddElement(String instanceId, String ref,byte[] dom,String index, String callback) {
    return callAddElement(instanceId,ref, new String(dom),index,callback);
  }

  /**
   * JavaScript uses this methods to call Android code
   *
   * @param instanceId
   * @param tasks
   * @param callback
   */

  public int callCreateBody(String instanceId, byte [] tasks, String callback) {
    return callCreateBody(instanceId,new String(tasks),callback);
  }

  public int callCreateBody(String instanceId, String tasks, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callCreateBody(instanceId, tasks, callback);
    }catch (Throwable e){
      //catch everything during call native.
      // if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callCreateBody throw exception:"+e.getMessage());
      // }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }


  /**
   * JSF render Node by callAddElement
   */
  public int callAddElement(String instanceId, String ref,String dom,String index, String callback) {

    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;

    try {
      errorCode = WXBridgeManager.getInstance().callAddElement(instanceId, ref,dom,index, callback);
    }catch (Throwable e){
      //catch everything during call native.
      // if(WXEnvironment.isApkDebugable()){
        e.printStackTrace();
        WXLogUtils.e(TAG,"callNative throw error:"+e.getMessage());
      // }
    }

    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    // if(WXEnvironment.isApkDebugable()){
      if(errorCode == IWXBridge.DESTROY_INSTANCE){
        WXLogUtils.w("destroyInstance :"+instanceId+" JSF must stop callNative");
      }
    // }
    return errorCode;
  }

  /**
   * Report JavaScript error.
   *
   * @param instanceId
   * @param func       exception function
   * @throws String exception
   */
  public void reportJSException(String instanceId, String func, String exception) {
    WXBridgeManager.getInstance().reportJSException(instanceId, func, exception);
  }

  /**
   * Bridge module Js Method
   * support Sync or Async through setting  Annotation as {@link com.taobao.weex.annotation.JSMethod }
   * @param instanceId  Instance ID
   * @param module  the name of module
   * @param method  the name of method
   * @param arguments  the arguments of the method
   * @param options  option arguments for extending
   * @return  the result
   */
  @Override
  public Object callNativeModule(String instanceId, String module, String method, byte [] arguments, byte [] options) {

    JSONArray argArray = JSON.parseArray(new String(arguments));
    JSONObject optionsObj = null;
    if (options != null) {
      optionsObj = JSON.parseObject(new String(options));
    }
    Object object =  WXBridgeManager.getInstance().callNativeModule(instanceId,module,method,argArray,optionsObj);
    return new WXJSObject(object);
  }

  /**
   * Bridge component Js Method
   * @param instanceId  Instance ID
   * @param componentRef  the ref of component
   * @param method  the name of method
   * @param arguments  the arguments of the method
   * @param options  option arguments for extending
   */
  @Override
  public void callNativeComponent(String instanceId, String componentRef, String method, byte [] arguments, byte [] options) {
    JSONArray argArray = JSON.parseArray(new String(arguments));
     WXBridgeManager.getInstance().callNativeComponent(instanceId,componentRef,method,argArray,options);
  }

  public void setTimeoutNative(String callbackId, String time) {
    WXBridgeManager.getInstance().setTimeout(callbackId, time);
  }

  public void setJSFrmVersion(String version) {
    if(!TextUtils.isEmpty(version)) {
      WXEnvironment.JS_LIB_SDK_VERSION = version;
    }
  }

  /**
   * JavaScript uses this methods to call Android code
   *
   * @param instanceId
   * @param tasks
   * @param callback
   */

  public int callUpdateFinish(String instanceId, byte [] tasks, String callback) {

    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callUpdateFinish(instanceId, callback);
    } catch (Throwable e) {
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callCreateBody throw exception:"+e.getMessage());
      }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   *
   * @param instanceId
   * @param tasks
   * @param callback
   */

  public int callCreateFinish(String instanceId, byte [] tasks, String callback) {

    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callCreateFinish(instanceId, callback);
    } catch (Throwable e) {
      //catch everything during call native.
      // if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callCreateFinish throw exception:" + e.getMessage());
      // }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   *
   * @param instanceId
   * @param tasks
   * @param callback
   */

  public int callRefreshFinish(String instanceId, byte [] tasks, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callRefreshFinish(instanceId, callback);
    } catch (Throwable e) {
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callCreateFinish throw exception:" + e.getMessage());
      }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   *
   * @param instanceId
   * @param tasks
   * @param callback
   */

  public int callUpdateAttrs(String instanceId, String ref, byte [] tasks, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callUpdateAttrs(instanceId, ref, new String(tasks), callback);
    } catch (Throwable e) {
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callUpdateAttrs throw exception:" + e.getMessage());
      }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   *
   * @param instanceId
   * @param tasks
   * @param callback
   */

  public int callUpdateStyle(String instanceId, String ref, byte [] tasks, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callUpdateStyle(instanceId, ref, new String(tasks), callback);
    } catch (Throwable e) {
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callUpdateStyle throw exception:" + e.getMessage());
      }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   * @param instanceId
   * @param ref
   * @param callback
   * @return int
   */

  public int callRemoveElement(String instanceId, String ref, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callRemoveElement(instanceId, ref, callback);
    } catch (Throwable e) {
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callRemoveElement throw exception:" + e.getMessage());
      }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   * @param instanceId
   * @param ref
   * @param parentref
   * @param index
   * @param callback
   * @return int
   */
  public int callMoveElement(String instanceId, String ref, String parentref, String index, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      // Integer.parseInt(index)
      errorCode = WXBridgeManager.getInstance().callMoveElement(instanceId, ref, parentref, index, callback);
    } catch (Throwable e) {
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callMoveElement throw exception:" + e.getMessage());
      }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   * @param instanceId
   * @param ref
   * @param event
   * @param callback
   * @return int
   */
  public int callAddEvent(String instanceId, String ref, String event, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callAddEvent(instanceId, ref, event, callback);
    } catch (Throwable e) {
      //catch everything during call native.
      // if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callAddEvent throw exception:" + e.getMessage());
      // }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  /**
   * JavaScript uses this methods to call Android code
   * @param instanceId
   * @param ref
   * @param event
   * @param callback
   * @return int
   */
  public int callRemoveEvent(String instanceId, String ref, String event, String callback) {
    long start = System.currentTimeMillis();
    WXSDKInstance instance = WXSDKManager.getInstance().getSDKInstance(instanceId);
    if(instance != null) {
      instance.firstScreenCreateInstanceTime(start);
    }
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callRemoveEvent(instanceId, ref, event, callback);
    } catch (Throwable e) {
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"callRemoveEvent throw exception:" + e.getMessage());
      }
    }
    if(instance != null) {
      instance.callNativeTime(System.currentTimeMillis() - start);
    }
    return errorCode;
  }

  public void reportServerCrash(String instanceId, String crashFile) {
    WXLogUtils.e(TAG,"reportServerCrash instanceId:" + instanceId);
    int errorCode = IWXBridge.INSTANCE_RENDERING;
    try {
      errorCode = WXBridgeManager.getInstance().callReportCrashReloadPage(instanceId, crashFile);

      // upload crash log
    }catch (Throwable e){
      //catch everything during call native.
      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.e(TAG,"reloadPageNative throw exception:"+e.getMessage());
      }
    }
  }

}
