/*
 * 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;

import android.app.AlertDialog;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.graphics.Color;
import android.graphics.Paint;
import android.net.Uri;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.annotation.RestrictTo;
import android.support.annotation.RestrictTo.Scope;
import android.support.annotation.WorkerThread;
import android.support.v4.util.ArrayMap;
import android.text.TextUtils;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;

import com.alibaba.fastjson.JSONObject;
import com.taobao.weex.adapter.IDrawableLoader;
import com.taobao.weex.adapter.IWXHttpAdapter;
import com.taobao.weex.adapter.IWXImgLoaderAdapter;
import com.taobao.weex.adapter.IWXUserTrackAdapter;
import com.taobao.weex.adapter.URIAdapter;
import com.taobao.weex.appfram.websocket.IWebSocketAdapter;
import com.taobao.weex.bridge.EventResult;
import com.taobao.weex.bridge.NativeInvokeHelper;
import com.taobao.weex.bridge.SimpleJSCallback;
import com.taobao.weex.bridge.WXBridgeManager;
import com.taobao.weex.bridge.WXModuleManager;
import com.taobao.weex.common.Constants;
import com.taobao.weex.common.Destroyable;
import com.taobao.weex.common.IWXDebugProxy;
import com.taobao.weex.common.OnWXScrollListener;
import com.taobao.weex.common.WXErrorCode;
import com.taobao.weex.common.WXModule;
import com.taobao.weex.common.WXPerformance;
import com.taobao.weex.common.WXPerformance.Dimension;
import com.taobao.weex.common.WXRefreshData;
import com.taobao.weex.common.WXRenderStrategy;
import com.taobao.weex.common.WXRequest;
import com.taobao.weex.common.WXResponse;
import com.taobao.weex.dom.WXEvent;
import com.taobao.weex.http.WXHttpUtil;
import com.taobao.weex.layout.ContentBoxMeasurement;
import com.taobao.weex.performance.WXAnalyzerDataTransfer;
import com.taobao.weex.tracing.WXTracing;
import com.taobao.weex.ui.action.GraphicActionAddElement;
import com.taobao.weex.ui.component.NestedContainer;
import com.taobao.weex.ui.component.WXBasicComponentType;
import com.taobao.weex.ui.component.WXComponent;
import com.taobao.weex.ui.component.WXComponentFactory;
import com.taobao.weex.ui.component.WXEmbed;
import com.taobao.weex.ui.flat.FlatGUIContext;
import com.taobao.weex.ui.view.WXScrollView;
import com.taobao.weex.utils.Trace;
import com.taobao.weex.utils.WXExceptionUtils;
import com.taobao.weex.utils.WXFileUtils;
import com.taobao.weex.utils.WXJsonUtils;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.WXReflectionUtils;
import com.taobao.weex.utils.WXUtils;

import java.io.Serializable;
import java.io.UnsupportedEncodingException;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

import static com.taobao.weex.http.WXHttpUtil.KEY_USER_AGENT;


/**
 * Each instance of WXSDKInstance represents an running weex instance.
 * It can be a pure weex view, or mixed with native view
 */
public class WXSDKInstance implements IWXActivityStateListener,View.OnLayoutChangeListener {

  private static  final  String SOURCE_TEMPLATE_BASE64_MD5 = "templateSourceBase64MD5";

  //Performance
  public boolean mEnd = false;
  public static final String BUNDLE_URL = "bundleUrl";
  private IWXUserTrackAdapter mUserTrackAdapter;
  private IWXRenderListener mRenderListener;
  private IWXStatisticsListener mStatisticsListener;
  /** package **/ Context mContext;
  private final String mInstanceId;
  private RenderContainer mRenderContainer;
  private WXComponent mRootComp;
  private boolean mRendered;
  private WXRefreshData mLastRefreshData;
  private NestedInstanceInterceptor mNestedInstanceInterceptor;
  private String mBundleUrl = "";
  public static String requestUrl = "requestUrl";
  private boolean isDestroy=false;
  private Map<String,Serializable> mUserTrackParams;
  private NativeInvokeHelper mNativeInvokeHelper;
  private boolean isCommit=false;
  private WXGlobalEventReceiver mGlobalEventReceiver=null;
  private boolean trackComponent;
  private boolean enableLayerType = true;
  private boolean mNeedValidate = false;
  private boolean mNeedReLoad = false;
  private int mInstanceViewPortWidth = 750;
  private @NonNull
  FlatGUIContext mFlatGUIContext =new FlatGUIContext();

  public long mRenderStartNanos;
  public int mExecJSTraceId = WXTracing.nextId();

  /**
   *for network tracker
   */
  public String mwxDims[] = new String [5];
  public long measureTimes[] = new long [5];

  public WeakReference<String> templateRef;
  public Map<String,List<String>> responseHeaders = new HashMap<>();

  /**
   * Render strategy.
   */
  private WXRenderStrategy mRenderStrategy = WXRenderStrategy.APPEND_ASYNC;

  /**
   * Render start time
   */
  public long mRenderStartTime;
  /**
   * Refresh start time
   */
  private long mRefreshStartTime;
  private WXPerformance mWXPerformance;
  private ScrollView mScrollView;
  private WXScrollView.WXScrollViewListener mWXScrollViewListener;

  private List<OnWXScrollListener> mWXScrollListeners;

  private List<String> mLayerOverFlowListeners;

  public List<String> getLayerOverFlowListeners() {
    return mLayerOverFlowListeners;
  }

  public void addLayerOverFlowListener(String ref) {
    if (mLayerOverFlowListeners == null)
      mLayerOverFlowListeners = new ArrayList<>();
    mLayerOverFlowListeners.add(ref);
  }

  public void removeLayerOverFlowListener(String ref) {
    if (mLayerOverFlowListeners != null)
      mLayerOverFlowListeners.remove(ref);
  }

  /**
   * whether we are in preRender mode
   * */
  private volatile boolean isPreRenderMode;

  private boolean mCurrentGround = false;
  private ComponentObserver mComponentObserver;
  private Map<String, GraphicActionAddElement> inactiveAddElementAction = new ArrayMap<>();

  private Map<Long, ContentBoxMeasurement> mContentBoxMeasurements = new ArrayMap<>();

  /**
   * set make weexCore run in single process mode
   * @param flag true means weexCore run in single process mode or multi process mode
   */
  public void setUseSingleProcess(boolean flag) {
    WXBridgeManager.getInstance().setUseSingleProcess(flag);
  }

  /**
   * set open SandBox
   * @param flag
   */
  public void setUseSandBox(boolean flag) {
    WXBridgeManager.getInstance().setSandBoxContext(flag);
  }

  public PriorityQueue<WXEmbed> hiddenEmbeds;

  private int maxHiddenEmbedsNum = -1; //max hidden embed num, -1 standard for ulimit

  public int getMaxHiddenEmbedsNum() {
    return maxHiddenEmbedsNum;
  }

  public void setMaxHiddenEmbedsNum(int maxHiddenEmbedsNum) {
    this.maxHiddenEmbedsNum = maxHiddenEmbedsNum;
  }

  @WorkerThread
  @RestrictTo(Scope.LIBRARY)
  public void addInActiveAddElementAction(String ref, GraphicActionAddElement action){
    inactiveAddElementAction.put(ref, action);
  }

  @WorkerThread
  @RestrictTo(Scope.LIBRARY)
  public void removeInActiveAddElmentAction(String ref){
    inactiveAddElementAction.remove(ref);
  }

  @WorkerThread
  @RestrictTo(Scope.LIBRARY)
  public GraphicActionAddElement getInActiveAddElementAction(String ref){
    return inactiveAddElementAction.get(ref);
  }

  /**
   * If anchor is created manually(etc. define a layout xml resource ),
   * be aware do not add it to twice when {@link IWXRenderListener#onViewCreated(WXSDKInstance, View)}.
   * @param a
   */
  public void setRenderContainer(RenderContainer a){
    if(a != null) {
      a.setSDKInstance(this);
      a.addOnLayoutChangeListener(this);
    }

    mRenderContainer = a;
    if (mRenderContainer != null && mRenderContainer.getLayoutParams() != null
            && mRenderContainer.getLayoutParams().width == ViewGroup.LayoutParams.WRAP_CONTENT) {
      WXBridgeManager.getInstance().post(new Runnable() {
        @Override
        public void run() {
          WXBridgeManager.getInstance().setRenderContentWrapContentToCore(true, getInstanceId());
        }
      });
    } else {
      WXBridgeManager.getInstance().post(new Runnable() {
        @Override
        public void run() {
          WXBridgeManager.getInstance().setRenderContentWrapContentToCore(false, getInstanceId());
        }
      });
    }
  }

  public boolean isTrackComponent() {
    return trackComponent;
  }

  public void setTrackComponent(boolean trackComponent) {
    this.trackComponent = trackComponent;
  }

  /**
   * Tell whether it is enabled to change the layerType
   * {@link android.view.View#setLayerType(int, Paint)}
   * @return True for enable to change the layerType of component, false otherwise. The default
   * is True
   */
  public boolean isLayerTypeEnabled() {
    return enableLayerType;
  }

  /**
   * Enable the ability of changing layerType. e.g. {@link android.view.View#setLayerType(int, Paint)}
   * Disable the ability of changing layerType will have tremendous <strong>performance
   * punishment</strong>.
   *
   * <strong>Do not</strong> set this to false unless you know exactly what you are doing.
   * @param enable True for enable to change the layerType of component, false otherwise. The default
   * is True
   */
  public void enableLayerType(boolean enable) {
    enableLayerType = enable;
  }

  @RestrictTo(RestrictTo.Scope.LIBRARY)
  public @NonNull
  FlatGUIContext getFlatUIContext(){
    return mFlatGUIContext;
  }

  public boolean isNeedValidate() {
    return mNeedValidate;
  }

  public boolean isNeedReLoad() {
    return mNeedReLoad;
  }

  public void setNeedLoad(boolean load) {
    mNeedReLoad = load;
  }

  public void setInstanceViewPortWidth(int instanceViewPortWidth) {
    this.mInstanceViewPortWidth = instanceViewPortWidth;
  }

  public int getInstanceViewPortWidth(){
    return mInstanceViewPortWidth;
  }

  public interface OnInstanceVisibleListener{
    void onAppear();
    void onDisappear();
  }
  private List<OnInstanceVisibleListener> mVisibleListeners = new ArrayList<>();

  public WXSDKInstance(Context context) {
    mInstanceId = WXSDKManager.getInstance().generateInstanceId();
    init(context);
  }

  /**
   * For unittest only.
   */
  @RestrictTo(Scope.TESTS)
  WXSDKInstance(Context context,String id) {
    mInstanceId = id;
    init(context);
  }

  public WXComponent getRootComponent() {
    return mRootComp;
  }

  public void setNestedInstanceInterceptor(NestedInstanceInterceptor interceptor){
    mNestedInstanceInterceptor = interceptor;
  }

  public final WXSDKInstance createNestedInstance(NestedContainer container){
    WXSDKInstance sdkInstance = newNestedInstance();
    if(mNestedInstanceInterceptor != null){
      mNestedInstanceInterceptor.onCreateNestInstance(sdkInstance,container);
    }
    if(sdkInstance != null){
        sdkInstance.setComponentObserver(this.getComponentObserver());
    }
    return sdkInstance;
  }

  protected WXSDKInstance newNestedInstance() {
    return new WXSDKInstance(mContext);
  }

  public void addOnInstanceVisibleListener(OnInstanceVisibleListener l){
    mVisibleListeners.add(l);
  }

  public void removeOnInstanceVisibleListener(OnInstanceVisibleListener l){
    mVisibleListeners.remove(l);
  }

  public void init(Context context) {
    mContext = context;
    mNativeInvokeHelper = new NativeInvokeHelper(mInstanceId);

    mWXPerformance = new WXPerformance();
    mWXPerformance.WXSDKVersion = WXEnvironment.WXSDK_VERSION;
    mWXPerformance.JSLibInitTime = WXEnvironment.sJSLibInitTime;

    mUserTrackAdapter=WXSDKManager.getInstance().getIWXUserTrackAdapter();
  }

  /**
   * Set a Observer for component.
   * This observer will be called in each component, should not doing
   * anything will impact render performance.
   *
   * @param observer
   */
  public void setComponentObserver(ComponentObserver observer){
    mComponentObserver = observer;
  }

  public ComponentObserver getComponentObserver(){
    return mComponentObserver;
  }

  public NativeInvokeHelper getNativeInvokeHelper() {
    return mNativeInvokeHelper;
  }

  @Deprecated
  public void setBizType(String bizType) {
    if (!TextUtils.isEmpty(bizType)) {
      mWXPerformance.bizType = bizType;
    }
  }

  public ScrollView getScrollView() {
    return mScrollView;
  }

  public void setRootScrollView(ScrollView scrollView) {
    mScrollView = scrollView;
    if (mWXScrollViewListener != null) {
      ((WXScrollView) mScrollView).addScrollViewListener(mWXScrollViewListener);
    }
  }

  @Deprecated
  public void registerScrollViewListener(WXScrollView.WXScrollViewListener scrollViewListener) {
    mWXScrollViewListener = scrollViewListener;
  }

  @Deprecated
  public WXScrollView.WXScrollViewListener getScrollViewListener() {
    return mWXScrollViewListener;
  }

  @Deprecated
  public void setIWXUserTrackAdapter(IWXUserTrackAdapter adapter) {
  }

  /**
   * Render template asynchronously, use {@link WXRenderStrategy#APPEND_ASYNC} as render strategy
   * @param template bundle js
   * @param options  os   iphone/android/ipad
   *                 weexversion    Weex version(like 1.0.0)
   *                 appversion     App version(like 1.0.0)
   *                 devid        Device id(like Aqh9z8dRJNBhmS9drLG5BKCmXhecHUXIZoXOctKwFebH)
   *                 sysversion    Device system version(like 5.4.4、7.0.4, should be used with os)
   *                 sysmodel     Device model(like iOS:"MGA82J/A", android:"MI NOTE LTE")
   *                 Time    UNIX timestamp, UTC+08:00
   *                 TTID(Optional)
   *                 MarkertId
   *                 Appname(Optional)  tm,tb,qa
   *                 Bundleurl(Optional)  template url
   * @param jsonInitData Initial data for rendering
   */
  public void render(String template, Map<String, Object> options, String jsonInitData) {
    render(template, options, jsonInitData, WXRenderStrategy.APPEND_ASYNC);
  }

  /**
   * Render template asynchronously
   * @param template bundle js
   * @param options  os   iphone/android/ipad
   *                 weexversion    Weex version(like 1.0.0)
   *                 appversion     App version(like 1.0.0)
   *                 devid        Device id(like Aqh9z8dRJNBhmS9drLG5BKCmXhecHUXIZoXOctKwFebH)
   *                 sysversion    Device system version(like 5.4.4、7.0.4, should be used with os)
   *                 sysmodel     Device model(like iOS:"MGA82J/A", android:"MI NOTE LTE")
   *                 Time    UNIX timestamp, UTC+08:00
   *                 TTID(Optional)
   *                 MarkertId
   *                 Appname(Optional)  tm,tb,qa
   *                 Bundleurl(Optional)  template url
   * @param jsonInitData Initial data for rendering
   * @param flag     RenderStrategy {@link WXRenderStrategy}
   */
  @Deprecated
  public void render(String template, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag) {
    render(WXPerformance.DEFAULT, template, options, jsonInitData, flag);
  }

  /**
   * Render template asynchronously
   *
   * @param pageName, used for performance log.
   * @param template bundle js
   * @param options  os   iphone/android/ipad
   *                 weexversion    Weex version(like 1.0.0)
   *                 appversion     App version(like 1.0.0)
   *                 devid        Device id(like Aqh9z8dRJNBhmS9drLG5BKCmXhecHUXIZoXOctKwFebH)
   *                 sysversion    Device system version(like 5.4.4、7.0.4, should be used with os)
   *                 sysmodel     Device model(like iOS:"MGA82J/A", android:"MI NOTE LTE")
   *                 Time    UNIX timestamp, UTC+08:00
   *                 TTID(Optional)
   *                 MarkertId
   *                 Appname(Optional)  tm,tb,qa
   *                 Bundleurl(Optional)  template url
   * @param jsonInitData Initial data for rendering
   * @param flag     RenderStrategy {@link WXRenderStrategy}
   */
  public void render(String pageName, String template, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag) {
    mWXPerformance.beforeInstanceRender(mInstanceId);

    if(WXEnvironment.isApkDebugable() && WXPerformance.DEFAULT.equals(pageName)){
      WXLogUtils.e("WXSDKInstance", "Please set your pageName or your js bundle url !!!!!!!");

      if (getUIContext() != null) {
        new AlertDialog.Builder(getUIContext())
                .setTitle("Error: Missing pageName")
                .setMessage("We highly recommend you to set pageName. Call" +
                        "\nWXSDKInstance#render(String pageName, String template, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag)\n" +
                        "to fix it.")
                .show();
      }

      return;
    }
    renderInternal(pageName,template,options,jsonInitData,flag);
  }

  private void ensureRenderArchor(){
    if(mRenderContainer == null){
      if (getContext() != null) {
        setRenderContainer(new RenderContainer(getContext()));
        mRenderContainer.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT, ViewGroup.LayoutParams.MATCH_PARENT));
        mRenderContainer.setBackgroundColor(Color.TRANSPARENT);
        mRenderContainer.setSDKInstance(this);
        mRenderContainer.addOnLayoutChangeListener(this);
      }
    }
  }

  private void renderInternal(String pageName,
                              String template,
                              Map<String, Object> options,
                              String jsonInitData,
                              WXRenderStrategy flag){
    if (mRendered || TextUtils.isEmpty(template)) {
      return;
    }

    mWXPerformance.pageName = (TextUtils.isEmpty(pageName) ? "defaultBundleUrl":pageName);
    if (TextUtils.isEmpty(mBundleUrl)) {
      mBundleUrl = mWXPerformance.pageName;
    }

    WXLogUtils.d("WXSDKInstance", "Start render page: " + pageName);

    if (WXTracing.isAvailable()) {
      WXTracing.TraceEvent traceEvent = WXTracing.newEvent("executeBundleJS", mInstanceId, -1);
      traceEvent.traceId = mExecJSTraceId;
      traceEvent.iid = mInstanceId;
      traceEvent.tname = "JSThread";
      traceEvent.ph = "B";
      traceEvent.submit();
      mRenderStartNanos = System.nanoTime();
    }

    ensureRenderArchor();

    Map<String, Object> renderOptions = options;
    if (renderOptions == null) {
      renderOptions = new HashMap<>();
    }

    if (WXEnvironment.sDynamicMode && !TextUtils.isEmpty(WXEnvironment.sDynamicUrl) && renderOptions.get("dynamicMode") == null) {
      renderOptions.put("dynamicMode", "true");
      renderByUrl(pageName, WXEnvironment.sDynamicUrl, renderOptions, jsonInitData, flag);
      return;
    }

    mWXPerformance.JSTemplateSize = template.length() / 1024f;

    mRenderStartTime = System.currentTimeMillis();
    mRenderStrategy = flag;

    WXSDKManager.getInstance().setCrashInfo(WXEnvironment.WEEX_CURRENT_KEY,pageName);

    WXSDKManager.getInstance().createInstance(this, template, renderOptions, jsonInitData);
    mRendered = true;
  }

  private void renderByUrlInternal(String pageName,
                                   final String url,
                                   Map<String, Object> options,
                                   final String jsonInitData,
                                   final WXRenderStrategy flag) {

    ensureRenderArchor();
    pageName = wrapPageName(pageName, url);
    mBundleUrl = url;
    if(WXSDKManager.getInstance().getValidateProcessor()!=null) {
      mNeedValidate = WXSDKManager.getInstance().getValidateProcessor().needValidate(mBundleUrl);
    }

    Map<String, Object> renderOptions = options;
    if (renderOptions == null) {
      renderOptions = new HashMap<>();
    }
    if (!renderOptions.containsKey(BUNDLE_URL)) {
      renderOptions.put(BUNDLE_URL, url);
    }

    Uri uri = Uri.parse(url);
    if (uri != null && TextUtils.equals(uri.getScheme(), "file")) {
      render(pageName, WXFileUtils.loadFileOrAsset(assembleFilePath(uri), mContext), renderOptions, jsonInitData, flag);
      return;
    }

    IWXHttpAdapter adapter = WXSDKManager.getInstance().getIWXHttpAdapter();

    WXRequest wxRequest = new WXRequest();
    wxRequest.url = rewriteUri(Uri.parse(url),URIAdapter.BUNDLE).toString();
    if(wxRequest != null && !TextUtils.isEmpty(wxRequest.url)){
      requestUrl = wxRequest.url;
    }else {
      requestUrl = pageName;
    }

    if (wxRequest.paramMap == null) {
      wxRequest.paramMap = new HashMap<String, String>();
    }
    wxRequest.instanceId = getInstanceId();
    wxRequest.paramMap.put(KEY_USER_AGENT, WXHttpUtil.assembleUserAgent(mContext,WXEnvironment.getConfig()));
    WXHttpListener httpListener =
            new WXHttpListener(pageName, renderOptions, jsonInitData, flag, System.currentTimeMillis());
    httpListener.setSDKInstance(this);
    adapter.sendRequest(wxRequest, (IWXHttpAdapter.OnHttpListener) httpListener);
  }

  /**
   * Use {@link #render(String, String, Map, String, WXRenderStrategy)} instead.
   * @param pageName
   * @param template
   * @param options
   * @param jsonInitData
   * @param width
   * @param height
   * @param flag
   */
  @Deprecated
  public void render(String pageName, String template, Map<String, Object> options, String jsonInitData, int width, int height, WXRenderStrategy flag) {
    render(pageName,template,options,jsonInitData,flag);
  }

  /**
   * Render template asynchronously, use {@link WXRenderStrategy#APPEND_ASYNC} as render strategy
   * @param template bundle js
   */
  public void render(String template) {
    render(WXPerformance.DEFAULT, template, null, null, mRenderStrategy);
  }

  /**
   * Use {@link #render(String)} instead.
   * @param template
   * @param width
   * @param height
   */
  @Deprecated
  public void render(String template, int width, int height) {
    render(template);
  }

  /**
   * Use {@link #renderByUrl(String, String, Map, String, WXRenderStrategy)} instead.
   * @param pageName
   * @param url
   * @param options
   * @param jsonInitData
   * @param width
   * @param height
   * @param flag
   */
  @Deprecated
  public void renderByUrl(String pageName, final String url, Map<String, Object> options, final String jsonInitData, final int width, final int height, final WXRenderStrategy flag){
    renderByUrl(pageName,url,options,jsonInitData,flag);
  }

  public void renderByUrl(String pageName, final String url, Map<String, Object> options, final String jsonInitData, final WXRenderStrategy flag) {
    renderByUrlInternal(pageName,url,options,jsonInitData,flag);
  }

  private String wrapPageName(String pageName, String url) {
    if(TextUtils.equals(pageName, WXPerformance.DEFAULT)){
      pageName = url;
      WXExceptionUtils.degradeUrl = pageName;
      try {
        Uri uri=Uri.parse(url);
        if(uri!=null){
          Uri.Builder builder=new Uri.Builder();
          builder.scheme(uri.getScheme());
          builder.authority(uri.getAuthority());
          builder.path(uri.getPath());
          pageName=builder.toString();
        }
      } catch (Exception e) {
      }
    }
    return pageName;
  }

  private String assembleFilePath(Uri uri) {
    if(uri!=null && uri.getPath()!=null){
      return uri.getPath().replaceFirst("/","");
    }
    return "";
  }

  public void reloadPage(boolean reloadThis) {

    WXSDKEngine.reload();

    if (reloadThis) {
      if (mContext != null)  {
        Intent intent = new Intent();
        intent.setAction(IWXDebugProxy.ACTION_INSTANCE_RELOAD);
        intent.putExtra("url", mBundleUrl);
        mContext.sendBroadcast(intent);
      }
      // mRendered = false;
      //    destroy();
      // renderInternal(mPackage, mTemplate, mOptions, mJsonInitData, mFlag);
      // refreshInstance("{}");
    }
  }

  /**
   * Refresh instance asynchronously.
   * @param data the new data
   */
  public void refreshInstance(Map<String, Object> data) {
    if (data == null) {
      return;
    }
    refreshInstance(WXJsonUtils.fromObjectToJSONString(data));
  }

  /**
   * Refresh instance asynchronously.
   * @param jsonData the new data
   */
  public void refreshInstance(String jsonData) {
    if (jsonData == null) {
      return;
    }
    mRefreshStartTime = System.currentTimeMillis();
    //cancel last refresh message
    if (mLastRefreshData != null) {
      mLastRefreshData.isDirty = true;
    }

    mLastRefreshData = new WXRefreshData(jsonData, false);

    WXSDKManager.getInstance().refreshInstance(mInstanceId, mLastRefreshData);
  }

  public WXRenderStrategy getRenderStrategy() {
    return mRenderStrategy;
  }

  public Context getUIContext() {
    return mContext;
  }

  public String getInstanceId() {
    return mInstanceId;
  }

  public Context getContext() {
    if(mContext == null){
      WXLogUtils.e("WXSdkInstance mContext == null");
    }
    return mContext;
  }

  public int getWeexHeight() {
    return mRenderContainer == null ? 0: mRenderContainer.getHeight();
  }

  public int getWeexWidth() {
    return mRenderContainer == null ? 0: mRenderContainer.getWidth();
  }


  public IWXImgLoaderAdapter getImgLoaderAdapter() {
    return WXSDKManager.getInstance().getIWXImgLoaderAdapter();
  }

  public IDrawableLoader getDrawableLoader() {
    return WXSDKManager.getInstance().getDrawableLoader();
  }

  public URIAdapter getURIAdapter(){
    return WXSDKManager.getInstance().getURIAdapter();
  }

  public Uri rewriteUri(Uri uri,String type){
    return getURIAdapter().rewrite(this,type,uri);
  }

  public IWXHttpAdapter getWXHttpAdapter() {
    return WXSDKManager.getInstance().getIWXHttpAdapter();
  }

  public IWXStatisticsListener getWXStatisticsListener() {
    return mStatisticsListener;
  }

  public @Nullable
  IWebSocketAdapter getWXWebSocketAdapter() {
    return WXSDKManager.getInstance().getIWXWebSocketAdapter();
  }

  @Deprecated
  public void reloadImages() {
    if (mScrollView == null) {
      return;
    }
  }


  public boolean isPreRenderMode() {
    return this.isPreRenderMode;
  }

  public void setPreRenderMode(final boolean isPreRenderMode) {
    WXSDKManager.getInstance().getWXRenderManager().postOnUiThread(new Runnable() {
      @Override
      public void run() {
        WXSDKInstance.this.isPreRenderMode = isPreRenderMode;
      }
    },0);
  }

  public void setContext(@NonNull Context context) {
    this.mContext = context;
  }

  /********************************
   * begin register listener
   ********************************************************/
  public void registerRenderListener(IWXRenderListener listener) {
    mRenderListener = listener;
  }

  @Deprecated
  public void registerActivityStateListener(IWXActivityStateListener listener) {

  }

  public void registerStatisticsListener(IWXStatisticsListener listener) {
    mStatisticsListener = listener;
  }

  /**set render start time*/
  public void setRenderStartTime(long renderStartTime) {
    this.mRenderStartTime = renderStartTime;
  }

  /********************************
   * end register listener
   ********************************************************/


  /********************************
   *  begin hook Activity life cycle callback
   ********************************************************/

  @Override
  public void onActivityCreate() {

    // module listen Activity onActivityCreate
    WXModuleManager.onActivityCreate(getInstanceId());

    if(mRootComp != null) {
      mRootComp.onActivityCreate();
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely,onActivityCreate can not be call!");
    }

    mGlobalEventReceiver=new WXGlobalEventReceiver(this);
    getContext().registerReceiver(mGlobalEventReceiver,new IntentFilter(WXGlobalEventReceiver.EVENT_ACTION));
  }

  @Override
  public void onActivityStart() {

    // module listen Activity onActivityCreate
    WXModuleManager.onActivityStart(getInstanceId());
    if(mRootComp != null) {
      mRootComp.onActivityStart();
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely,onActivityStart can not be call!");
    }

  }

  public boolean onCreateOptionsMenu(Menu menu) {

    WXModuleManager.onCreateOptionsMenu(getInstanceId(),menu);
    if(mRootComp != null) {
      mRootComp.onCreateOptionsMenu(menu);
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely,onActivityStart can not be call!");
    }
    return true;
  }

  @Override
  public void onActivityPause() {
    onViewDisappear();
    if(!isCommit){
      Set<String> componentTypes= WXComponentFactory.getComponentTypesByInstanceId(getInstanceId());
      if(componentTypes!=null && componentTypes.contains(WXBasicComponentType.SCROLLER)){
        mWXPerformance.useScroller=1;
      }
      mWXPerformance.wxDims = mwxDims;
      mWXPerformance.measureTimes = measureTimes;
      if (mUserTrackAdapter != null) {
        mUserTrackAdapter.commit(mContext, null, IWXUserTrackAdapter.LOAD, mWXPerformance, getUserTrackParams());
      }
      WXAnalyzerDataTransfer.transferPerformance(mWXPerformance, getInstanceId());
      isCommit=true;
    }
    // module listen Activity onActivityPause
    WXModuleManager.onActivityPause(getInstanceId());
    if(mRootComp != null) {
      mRootComp.onActivityPause();
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely,onActivityPause can not be call!");
    }

    WXLogUtils.i("Application onActivityPause()");
    if (!mCurrentGround) {
      WXLogUtils.i("Application to be in the backround");
      Intent intent = new Intent(WXGlobalEventReceiver.EVENT_ACTION);
      intent.putExtra(WXGlobalEventReceiver.EVENT_NAME, Constants.Event.PAUSE_EVENT);
      intent.putExtra(WXGlobalEventReceiver.EVENT_WX_INSTANCEID, getInstanceId());
      mContext.sendBroadcast(intent);
      this.mCurrentGround = true;
    }
  }


  @Override
  public void onActivityResume() {

    // notify onActivityResume callback to module
    WXModuleManager.onActivityResume(getInstanceId());

    if(mRootComp != null) {
      mRootComp.onActivityResume();
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely, onActivityResume can not be call!");
    }

    if (mCurrentGround) {
      WXLogUtils.i("Application  to be in the foreground");
      Intent intent = new Intent(WXGlobalEventReceiver.EVENT_ACTION);
      intent.putExtra(WXGlobalEventReceiver.EVENT_NAME, Constants.Event.RESUME_EVENT);
      intent.putExtra(WXGlobalEventReceiver.EVENT_WX_INSTANCEID, getInstanceId());
      //todo tmp solution for gray version
      if (null != mContext){
        mContext.sendBroadcast(intent);
      }else {
        WXEnvironment.getApplication().sendBroadcast(intent);
      }
      this.mCurrentGround = false;
    }

    onViewAppear();
  }

  @Override
  public void onActivityStop() {

    // notify onActivityResume callback to module
    WXModuleManager.onActivityStop(getInstanceId());

    if(mRootComp != null) {
      mRootComp.onActivityStop();
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely, onActivityStop can not be call!");
    }


  }

  @Override
  public void onActivityDestroy() {
    WXModuleManager.onActivityDestroy(getInstanceId());

    if(mRootComp != null) {
      mRootComp.onActivityDestroy();
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely, onActivityDestroy can not be call!");
    }

    destroy();
  }

  @Override
  public boolean onActivityBack() {

    WXModuleManager.onActivityBack(getInstanceId());

    if(mRootComp != null) {
      return mRootComp.onActivityBack();
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely, onActivityBack can not be call!");
    }

    return false;
  }

  public boolean onBackPressed() {
    WXComponent comp = getRootComponent();
    if(comp != null) {
      WXEvent events= comp.getEvents();
      boolean hasNativeBackHook = events.contains(Constants.Event.NATIVE_BACK);
      if (hasNativeBackHook) {
        EventResult result = comp.fireEventWait(Constants.Event.NATIVE_BACK, null);
        if (WXUtils.getBoolean(result.getResult(), false)) {
          return true;
        }
      }

      boolean hasBackPressed = events.contains(Constants.Event.CLICKBACKITEM);
      if (hasBackPressed) {
        fireEvent(comp.getRef(), Constants.Event.CLICKBACKITEM,null, null);
      }
      return hasBackPressed;
    }
    return false;
  }

  public void onActivityResult(int requestCode, int resultCode, Intent data){
    WXModuleManager.onActivityResult(getInstanceId(),requestCode,resultCode,data);

    if(mRootComp != null) {
      mRootComp.onActivityResult(requestCode,resultCode,data);
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely, onActivityResult can not be call!");
    }
  }


  public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {

    WXModuleManager.onRequestPermissionsResult(getInstanceId(),requestCode,permissions,grantResults);

    if(mRootComp != null) {
       mRootComp.onRequestPermissionsResult(requestCode,permissions,grantResults);
    }else{
      WXLogUtils.w("Warning :Component tree has not build completely, onRequestPermissionsResult can not be call!");
    }
  }

  /********************************
   *  end hook Activity life cycle callback
   ********************************************************/

  public void onViewDisappear(){
    WXComponent comp = getRootComponent();
    if(comp != null) {
      fireEvent(comp.getRef(), Constants.Event.VIEWDISAPPEAR, null, null);
      //call disappear of nested instances
      for(OnInstanceVisibleListener instance:mVisibleListeners){
        instance.onDisappear();
      }
    }
  }

  public void onViewAppear(){
    WXComponent comp = getRootComponent();
    if(comp != null) {
      fireEvent( comp.getRef(), Constants.Event.VIEWAPPEAR,null, null);
      for(OnInstanceVisibleListener instance:mVisibleListeners){
        instance.onAppear();
      }
    }
  }


  public void onCreateFinish() {
    if (null != mWXPerformance){
      mWXPerformance.callCreateFinishTime=System.currentTimeMillis()-mWXPerformance
              .renderTimeOrigin;
    }
    if (mContext != null) {
      runOnUiThread(new Runnable() {

        @Override
        public void run() {
          if ( mContext != null) {
            onViewAppear();
            View wxView= mRenderContainer;
            if(mRenderListener != null) {
              mRenderListener.onViewCreated(WXSDKInstance.this, wxView);
            }
            if (mStatisticsListener != null) {
              mStatisticsListener.onFirstView();
            }
          }
        }
      });
    }
  }

  /**
   * call back when update finish
   */
  public void onUpdateFinish() {
    WXLogUtils.d("Instance onUpdateSuccess");
  }


  public void runOnUiThread(Runnable action) {
    WXSDKManager.getInstance().postOnUiThread(action, 0);
  }

  public void onRenderSuccess(final int width, final int height) {
    firstScreenRenderFinished();

    long time = System.currentTimeMillis() - mRenderStartTime;
    long[] renderFinishTime = WXBridgeManager.getInstance().getRenderFinishTime(getInstanceId());
    WXLogUtils.renderPerformanceLog("onRenderSuccess", time);
    WXLogUtils.renderPerformanceLog("   invokeCreateInstance",mWXPerformance.communicateTime);
    WXLogUtils.renderPerformanceLog("   onRenderSuccessCallBridgeTime", renderFinishTime[0]);
    WXLogUtils.renderPerformanceLog("   onRenderSuccessCssLayoutTime", renderFinishTime[1]);
    WXLogUtils.renderPerformanceLog("   onRenderSuccessParseJsonTime", renderFinishTime[2]);

    mWXPerformance.callBridgeTime = renderFinishTime[0];
    mWXPerformance.cssLayoutTime = renderFinishTime[1];
    mWXPerformance.parseJsonTime = renderFinishTime[2];

    mWXPerformance.totalTime = time;
    if(mWXPerformance.screenRenderTime<0.001){
      mWXPerformance.screenRenderTime =  time;
    }
    WXLogUtils.d(WXLogUtils.WEEX_PERF_TAG, "mComponentNum:" + mWXPerformance.componentCount);

    if (mRenderListener != null && mContext != null) {
      runOnUiThread(new Runnable() {

        @Override
        public void run() {
          if (mRenderListener != null && mContext != null) {
            mRenderListener.onRenderSuccess(WXSDKInstance.this, width, height);
            if (mUserTrackAdapter != null) {
              WXPerformance performance=new WXPerformance();
              performance.errCode=WXErrorCode.WX_SUCCESS.getErrorCode();
              performance.args=getBundleUrl();
              mUserTrackAdapter.commit(mContext,null,IWXUserTrackAdapter.JS_BRIDGE,performance,getUserTrackParams());
            }

            WXLogUtils.d(WXLogUtils.WEEX_PERF_TAG, mWXPerformance.toString());
          }
        }
      });
    }
    if(!WXEnvironment.isApkDebugable()){
      WXLogUtils.e("weex_perf",mWXPerformance.getPerfData());
    }
  }

  public void onRefreshSuccess(final int width, final int height) {
    WXLogUtils.renderPerformanceLog("onRefreshSuccess", (System.currentTimeMillis() - mRefreshStartTime));
    if (mRenderListener != null && mContext != null) {
      runOnUiThread(new Runnable() {

        @Override
        public void run() {
          if (mRenderListener != null && mContext != null) {
            mRenderListener.onRefreshSuccess(WXSDKInstance.this, width, height);
          }
        }
      });
    }
  }

  /**
   * when add/rm/mv element
   */
  public void onElementChange(){
    if (isDestroy() || !mEnd ||null == mRenderContainer || mRenderContainer.isPageHasEvent() ||
            mWXPerformance == null){
      return;
    }
    long lazyLoadTime = System.currentTimeMillis()- mWXPerformance.renderTimeOrigin - mWXPerformance
            .callCreateFinishTime;
    if (lazyLoadTime > 8000){
      //bad case
      return;
    }
    getWXPerformance().interactionTime = mWXPerformance.callCreateFinishTime + lazyLoadTime;
  }

  public void onRenderError(final String errCode, final String msg) {
    if (mRenderListener != null && mContext != null) {
      runOnUiThread(new Runnable() {

        @Override
        public void run() {
          if (mRenderListener != null && mContext != null) {
            mRenderListener.onException(WXSDKInstance.this, errCode, msg);
          }
        }
      });
    }
  }

  public void onJSException(final String errCode, final String function, final String exception) {
    if (mRenderListener != null && mContext != null) {
      runOnUiThread(new Runnable() {

        @Override
        public void run() {
          if (mRenderListener != null && mContext != null) {
            StringBuilder builder = new StringBuilder();
            builder.append(function);
            builder.append(exception);
            mRenderListener.onException(WXSDKInstance.this, errCode, builder.toString());
          }
        }
      });
    }
  }


  @Override
  public final void onLayoutChange(View v, int left, int top, int right, int bottom, int oldLeft, int
          oldTop, int oldRight, int oldBottom) {
    if (left != oldLeft || top != oldTop || right != oldRight || bottom != oldBottom) {
      onLayoutChange(v);
    }
  }

  /**
   * Subclass should override this method to get notifications of layout change of GodView.
   * @param godView the godView.
   */
  public void onLayoutChange(View godView) {

  }

  private boolean mCreateInstance =true;
  public void firstScreenCreateInstanceTime(long time) {
    if(mCreateInstance) {
      mWXPerformance.firstScreenJSFExecuteTime = time -mRenderStartTime;
      mCreateInstance =false;
    }
  }

  public void callJsTime(final long time){
    if (!mEnd){
      mWXPerformance.fsCallJsTotalTime+=time;
      mWXPerformance.fsCallJsTotalNum++;
    }
  }

  public void onComponentCreate(WXComponent component,long createTime) {
      mWXPerformance.mActionAddElementCount++;
      mWXPerformance.mActionAddElementSumTime += createTime;
      if (!mEnd){
        mWXPerformance.fsComponentCreateTime+=createTime;
        mWXPerformance.fsComponentCount++;
      }
      mWXPerformance.componentCount++;
      mWXPerformance.componentCreateTime+=createTime;
  }

  public void callActionAddElementTime(long time) {
      mWXPerformance.mActionAddElementSumTime += time;
  }

  public void firstScreenRenderFinished() {
      if (mEnd)
          return;

      mEnd = true;

      if (mStatisticsListener != null && mContext != null) {
          runOnUiThread(new Runnable() {
              @Override
              public void run() {
                  if (mStatisticsListener != null && mContext != null) {
                      Trace.beginSection("onFirstScreen");
                      mStatisticsListener.onFirstScreen();
                      Trace.endSection();
                  }
              }
          });
      }

      mWXPerformance.screenRenderTime = System.currentTimeMillis() - mRenderStartTime;
      mWXPerformance.fsRenderTime = System.currentTimeMillis();
      long[] fitstScreenPerformance = WXBridgeManager.getInstance().getFirstScreenRenderTime(getInstanceId());
      WXLogUtils.renderPerformanceLog("firstScreenRenderFinished", mWXPerformance.screenRenderTime);
      WXLogUtils.renderPerformanceLog("    firstScreenJSFExecuteTime", mWXPerformance.firstScreenJSFExecuteTime);
      WXLogUtils.renderPerformanceLog("    firstScreenCallBridgeTime", fitstScreenPerformance[0]);
      WXLogUtils.renderPerformanceLog("    firstScreenCssLayoutTime", fitstScreenPerformance[1]);
      WXLogUtils.renderPerformanceLog("    firstScreenParseJsonTime", fitstScreenPerformance[2]);
  }

  public void createInstanceFinished(long time) {

  }

  private void destroyView(View rootView) {
    try {
      if (rootView instanceof ViewGroup) {
        ViewGroup cViewGroup = ((ViewGroup) rootView);
        for (int index = 0; index < cViewGroup.getChildCount(); index++) {
          destroyView(cViewGroup.getChildAt(index));
        }

        cViewGroup.removeViews(0, ((ViewGroup) rootView).getChildCount());
        // Ensure that the viewgroup's status to be normal
        WXReflectionUtils.setValue(rootView, "mChildrenCount", 0);

      }
      if(rootView instanceof Destroyable){
        ((Destroyable)rootView).destroy();
      }
    } catch (Exception e) {
      WXLogUtils.e("WXSDKInstance destroyView Exception: ", e);
    }
  }

  public synchronized void destroy() {
    if(!isDestroy()) {
      if(mRendered) {
        WXSDKManager.getInstance().destroyInstance(mInstanceId);
      }
      WXComponentFactory.removeComponentTypesByInstanceId(getInstanceId());

      if (mGlobalEventReceiver != null) {
        getContext().unregisterReceiver(mGlobalEventReceiver);
        mGlobalEventReceiver = null;
      }
      if (mRootComp != null) {
        mRootComp.destroy();
        destroyView(mRenderContainer);
        mRootComp = null;
      }

      if (mGlobalEvents != null) {
        mGlobalEvents.clear();
      }

      if (mComponentObserver != null) {
        mComponentObserver = null;
      }

      if (mLayerOverFlowListeners != null) {
        mLayerOverFlowListeners.clear();
      }

      getFlatUIContext().destroy();
      mFlatGUIContext = null;

      mWXScrollListeners = null;
      mRenderContainer = null;
      mNestedInstanceInterceptor = null;
      mUserTrackAdapter = null;
      mScrollView = null;
      mContext = null;
      mRenderListener = null;
      isDestroy = true;
      mStatisticsListener = null;
      if(responseHeaders != null){
        responseHeaders.clear();
      }
      if(templateRef != null){
        templateRef = null;
      }
      if (null != mContentBoxMeasurements) {
        mContentBoxMeasurements.clear();
      }
      mWXPerformance.afterInstanceDestroy(mInstanceId);

      WXBridgeManager.getInstance().post(new Runnable() {
        @Override
        public void run() {
          WXBridgeManager.getInstance().onInstanceClose(getInstanceId());
          inactiveAddElementAction.clear();
        }
      });
    }
  }

  public boolean isDestroy(){
    return isDestroy;
  }

  /**
   * @return If you use render () the return value may be empty
   */
  public @Nullable String getBundleUrl() {
    return mBundleUrl;
  }

  public View getRootView() {
    if (mRootComp == null)
      return null;
    return mRootComp.getRealView();
  }

  public View getContainerView() {
    return mRenderContainer;
  }

  @Deprecated
  public void setBundleUrl(String url){
    mBundleUrl = url;
    if(WXSDKManager.getInstance().getValidateProcessor()!=null) {
      mNeedValidate = WXSDKManager.getInstance().getValidateProcessor().needValidate(mBundleUrl);
    }
  }

  public void onRootCreated(WXComponent root) {
    this.mRootComp = root;
    this.mRootComp.deepInComponentTree=1;
    mRenderContainer.addView(root.getHostView());
    setSize(mRenderContainer.getWidth(),mRenderContainer.getHeight());
  }

  /**
   * Move fixed view to container ,except it's already moved.
   * @param fixedChild
   */
  public void moveFixedView(View fixedChild){
    if(mRenderContainer != null) {
      ViewGroup parent;
      if((parent = (ViewGroup) fixedChild.getParent()) != null){
        if (parent != mRenderContainer) {
          parent.removeView(fixedChild);
          mRenderContainer.addView(fixedChild);
        }
      }else{
        mRenderContainer.addView(fixedChild);
      }
    }
  }

  public void removeFixedView(View fixedChild){
    if(mRenderContainer != null) {
      mRenderContainer.removeView(fixedChild);
    }
  }

  public int getRenderContainerPaddingLeft() {
    if(mRenderContainer != null) {
      return mRenderContainer.getPaddingLeft();
    }
    return 0;
  }

  public int getRenderContainerPaddingTop() {
    if(mRenderContainer != null) {
      return mRenderContainer.getPaddingTop();
    }
    return 0;
  }

  public synchronized List<OnWXScrollListener> getWXScrollListeners() {
    return mWXScrollListeners;
  }

  public synchronized void registerOnWXScrollListener(OnWXScrollListener wxScrollListener) {
    if(mWXScrollListeners==null){
      mWXScrollListeners=new ArrayList<>();
    }
    mWXScrollListeners.add(wxScrollListener);
  }

  public void setSize(int width, int height) {
    if (width > 0 && height > 0 & !isDestroy && mRendered && mRenderContainer != null) {
      ViewGroup.LayoutParams layoutParams = mRenderContainer.getLayoutParams();
      if (layoutParams != null) {
        final float realWidth = width;
        final float realHeight = height;
        if (mRenderContainer.getWidth() != width || mRenderContainer.getHeight() != height) {
          layoutParams.width = width;
          layoutParams.height = height;
          mRenderContainer.setLayoutParams(layoutParams);
        }

        if (mRootComp != null && layoutParams != null) {
          final boolean isWidthWrapContent = layoutParams.width == ViewGroup.LayoutParams.WRAP_CONTENT;
          final boolean isHeightWrapContent = layoutParams.height == ViewGroup.LayoutParams.WRAP_CONTENT;

          WXBridgeManager.getInstance().post(new Runnable() {
            @Override
            public void run() {
              WXBridgeManager.getInstance().setDefaultRootSize(getInstanceId(), realWidth, realHeight, isWidthWrapContent,
                      isHeightWrapContent);
            }
          });
        }
      }
    }
  }

  /*Global Event*/
  private HashMap<String, List<String>> mGlobalEvents = new HashMap<>();

  public void fireGlobalEventCallback(String eventName, Map<String,Object> params){
    List<String> callbacks=mGlobalEvents.get(eventName);
    if(callbacks!=null){
      for(String callback:callbacks){
        WXSDKManager.getInstance().callback(mInstanceId,callback,params,true);
      }
    }
  }

  /**
   * Fire event callback on a element.
   * @param elementRef
   * @param type
   * @param data
   * @param domChanges
   */
  public void fireEvent(String elementRef,final String type, final Map<String, Object> data,final Map<String, Object> domChanges, List<Object> eventArgs){
    fireEvent(elementRef, type, data, domChanges, eventArgs, null);
  }

  public void fireEvent(String elementRef,final String type, final Map<String, Object> data,final Map<String, Object> domChanges, List<Object> eventArgs, EventResult callback) {
    if (null != mWXPerformance && mWXPerformance.fsCallEventTotalNum<Integer.MAX_VALUE){
      mWXPerformance.fsCallEventTotalNum++;
    }
    WXBridgeManager.getInstance().fireEventOnNode(getInstanceId(),elementRef,type,data,domChanges, eventArgs, callback);
  }
  /**
   * Fire event callback on a element.
   * @param elementRef
   * @param type
   * @param data
   * @param domChanges
   */
  public void fireEvent(String elementRef,final String type, final Map<String, Object> data,final Map<String, Object> domChanges){
    fireEvent(elementRef, type, data, domChanges, null);
  }

  public void fireEvent(String elementRef,final String type, final Map<String, Object> data){
    fireEvent(elementRef,type,data,null);
  }

  public void fireEvent(String ref, String type){
    fireEvent(ref,type,new HashMap<String, Object>());
  }

  protected void addEventListener(String eventName, String callback) {
    if (TextUtils.isEmpty(eventName) || TextUtils.isEmpty(callback)) {
      return;
    }
    List<String> callbacks = mGlobalEvents.get(eventName);
    if (callbacks == null) {
      callbacks = new ArrayList<>();
      mGlobalEvents.put(eventName, callbacks);
    }
    callbacks.add(callback);
  }
  protected void removeEventListener(String eventName, String callback) {
    if (TextUtils.isEmpty(eventName) || TextUtils.isEmpty(callback)) {
      return;
    }
    List<String> callbacks = mGlobalEvents.get(eventName);
    if (callbacks != null) {
      callbacks.remove(callback);
    }
  }

  protected void removeEventListener(String eventName) {
    if (TextUtils.isEmpty(eventName)) {
      return;
    }
    mGlobalEvents.remove(eventName);
  }

  /**
   * Notifies WEEX that this event has occurred
   * @param eventName WEEX register event
   * @param module Events occur in this Module
   * @param params The parameters to be notified to WEEX are required
   */
  public void fireModuleEvent(String eventName, WXModule module,Map<String, Object> params) {
    if (TextUtils.isEmpty(eventName) || module == null) {
      return;
    }

    Map<String, Object> event = new HashMap<>();
    event.put("type", eventName);
    event.put("module", module.getModuleName());
    event.put("data", params);

    List<String> callbacks = module.getEventCallbacks(eventName);
    if (callbacks != null) {
      for (String callback : callbacks) {
        SimpleJSCallback jsCallback = new SimpleJSCallback(mInstanceId, callback);
        if (module.isOnce(callback)) {
          jsCallback.invoke(event);
        } else {
          jsCallback.invokeAndKeepAlive(event);
        }
      }
    }
  }

  /**
   * Check whether the current module registered the event
   * @param eventName EventName register in weex
   * @param module Events occur in this Module
   * @return  register->true
   */
  public boolean checkModuleEventRegistered(String eventName,WXModule module) {
    if (module != null) {
      List<String> events = module.getEventCallbacks(eventName);
      if (events != null && events.size() > 0) {
        return true;
      }
    }
    return false;
  }

  public WXPerformance getWXPerformance(){
    return mWXPerformance;
  }

  public Map<String, Serializable> getUserTrackParams() {
    return mUserTrackParams;
  }

  public void addUserTrackParameter(String key,Serializable value){
    if(this.mUserTrackParams == null){
      this.mUserTrackParams = new ConcurrentHashMap<>();
    }
    mUserTrackParams.put(key,value);
  }

  public void clearUserTrackParameters(){
    if(this.mUserTrackParams != null){
      this.mUserTrackParams.clear();
    }
  }

  public void removeUserTrackParameter(String key){
    if(this.mUserTrackParams != null){
      this.mUserTrackParams.remove(key);
    }
  }

  public void setMaxDomDeep(int maxDomDeep){
    if (null == mWXPerformance){
      return;
    }
    if (mWXPerformance.maxDeepVDomLayer <= maxDomDeep){
      mWXPerformance.maxDeepVDomLayer = maxDomDeep;
    }
  }

  public void onHttpStart(){
    if (!mEnd){
      mWXPerformance.fsRequestNum++;
    }
  }

  /**
   * load bundle js listener
   */
  class WXHttpListener implements IWXHttpAdapter.OnHttpListener {

    private String pageName;
    private Map<String, Object> options;
    private String jsonInitData;
    private WXRenderStrategy flag;
    private WXSDKInstance instance;
    private long startRequestTime;
    private int traceId;

    private WXHttpListener(String pageName, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag, long startRequestTime) {
      this.pageName = pageName;
      this.options = options;
      this.jsonInitData = jsonInitData;
      this.flag = flag;
      this.startRequestTime = startRequestTime;
      this.traceId = WXTracing.nextId();

      if (WXTracing.isAvailable()) {
        WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", mInstanceId, -1);
        event.iid = mInstanceId;
        event.tname = "Network";
        event.ph = "B";
        event.traceId = traceId;
        event.submit();
      }
    }

    public void setSDKInstance(WXSDKInstance instance) {
      this.instance = instance;
    }

    @Override
    public void onHttpStart() {
      if (this.instance != null
              && this.instance.getWXStatisticsListener() != null) {
        this.instance.getWXStatisticsListener().onHttpStart();
      }
    }

    @Override
    public void onHeadersReceived(int statusCode, Map<String,List<String>> headers) {
      if (this.instance != null
              && this.instance.getWXStatisticsListener() != null) {
        this.instance.getWXStatisticsListener().onHeadersReceived();
        this.instance.onHttpStart();
      }
      if(this.instance != null
              && this.instance.responseHeaders != null
              && headers != null){
        this.instance.responseHeaders.putAll(headers);
      }
    }

    @Override
    public void onHttpUploadProgress(int uploadProgress) {

    }

    @Override
    public void onHttpResponseProgress(int loadedLength) {

    }

    @Override
    public void onHttpFinish(WXResponse response) {
      if (this.instance != null
              && this.instance.getWXStatisticsListener() != null) {
        this.instance.getWXStatisticsListener().onHttpFinish();
      }

      if (WXTracing.isAvailable()) {
        WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", mInstanceId, -1);
        event.traceId = traceId;
        event.tname = "Network";
        event.ph = "E";
        event.extParams = new HashMap<>();
        if (response != null && response.originalData != null) {
          event.extParams.put("BundleSize", response.originalData.length);
        }
        event.submit();
      }

      mWXPerformance.networkTime = System.currentTimeMillis() - startRequestTime;
      if(response.extendParams!=null){
        Object actualNetworkTime=response.extendParams.get("actualNetworkTime");
        mWXPerformance.actualNetworkTime=actualNetworkTime instanceof Long?(long)actualNetworkTime:0;
        WXLogUtils.renderPerformanceLog("actualNetworkTime", mWXPerformance.actualNetworkTime);

        Object pureNetworkTime=response.extendParams.get("pureNetworkTime");
        mWXPerformance.pureNetworkTime=pureNetworkTime instanceof Long?(long)pureNetworkTime:0;
        WXLogUtils.renderPerformanceLog("pureNetworkTime", mWXPerformance.pureNetworkTime);

        Object connectionType=response.extendParams.get("connectionType");
        mWXPerformance.connectionType=connectionType instanceof String?(String)connectionType:"";

        Object packageSpendTime=response.extendParams.get("packageSpendTime");
        mWXPerformance.packageSpendTime=packageSpendTime instanceof Long ?(long)packageSpendTime:0;

        Object syncTaskTime=response.extendParams.get("syncTaskTime");
        mWXPerformance.syncTaskTime=syncTaskTime instanceof Long ?(long)syncTaskTime:0;

        Object requestType=response.extendParams.get("requestType");
        mWXPerformance.requestType=requestType instanceof String?(String)requestType:"none";

        Object cacheType = response.extendParams.get(Dimension.cacheType.toString());
        if(cacheType instanceof String){
          mWXPerformance.cacheType = (String) cacheType;
        }

        Object zCacheInfo = response.extendParams.get("zCacheInfo");
        mWXPerformance.zCacheInfo = zCacheInfo instanceof String?(String)zCacheInfo:"";

        if(isNet(mWXPerformance.requestType) && mUserTrackAdapter!=null){
          WXPerformance performance=new WXPerformance();
          if(!TextUtils.isEmpty(mBundleUrl)){
            try {
              performance.args= Uri.parse(mBundleUrl).buildUpon().clearQuery().toString();
            } catch (Exception e) {
              performance.args=pageName;
            }
          }
          if(!"200".equals(response.statusCode)){
            performance.errCode=WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
            performance.appendErrMsg(response.errorCode);
            performance.appendErrMsg("|");
            performance.appendErrMsg(response.errorMsg);

          }else if("200".equals(response.statusCode) && (response.originalData==null || response.originalData.length<=0)){
            performance.errCode=WXErrorCode.WX_ERR_JSBUNDLE_DOWNLOAD.getErrorCode();
            performance.appendErrMsg(response.statusCode);
            performance.appendErrMsg("|template is null!");
          }else {
            performance.errCode=WXErrorCode.WX_SUCCESS.getErrorCode();
          }

          if (mUserTrackAdapter != null) {
            mUserTrackAdapter.commit(getContext(), null, IWXUserTrackAdapter.JS_DOWNLOAD, performance, null);
          }
        }
      }
      WXLogUtils.renderPerformanceLog("networkTime", mWXPerformance.networkTime);
      if (response!=null && response.originalData!=null && TextUtils.equals("200", response.statusCode)) {
        String template = new String(response.originalData);
        render(pageName, template, options, jsonInitData, flag);

        // check content-type
      } else if (TextUtils.equals(WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode(),
              response.statusCode)) {
        WXLogUtils.e("user intercept: WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR");
        onRenderError(WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode(),
                "|response.errorMsg==" + response.errorMsg +
                        "|instance.getTemplateInfo == \n" + instance.getTemplateInfo() +
                        "|instance bundleUrl = \n" + instance.getBundleUrl() +
                        "|instance requestUrl = \n" + Uri.decode(WXSDKInstance.requestUrl)
        );

        // check content-length
      } else if (response!=null && response.originalData!=null && TextUtils.equals("-206", response.statusCode)) {
        WXLogUtils.e("user intercept: WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED");
        onRenderError(
                WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode(),
                WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode() +
                        "|response.errorMsg==" + response.errorMsg +
                        "|instance.getTemplateInfo == \n" + instance.getTemplateInfo());
      }
      else {
        onRenderError(WXErrorCode.WX_DEGRAD_ERR_NETWORK_BUNDLE_DOWNLOAD_FAILED.getErrorCode(),
                response.errorMsg);
      }
    }
  }

  private boolean isNet(String requestType){

    return "network".equals(requestType) || "2g".equals(requestType) || "3g".equals(requestType)
            || "4g".equals(requestType) || "wifi".equals(requestType) || "other".equals(requestType)
            || "unknown".equals(requestType);
  }

  /**
   * return md5, and bytes length
   * */
  public String getTemplateInfo() {
    String template = getTemplate();
    if(template == null){
      return " template md5 null " + JSONObject.toJSONString(responseHeaders);
    }
    if(TextUtils.isEmpty(template)){
      return " template md5  length 0 " + JSONObject.toJSONString(responseHeaders);
    }
    try {
      byte[] bts = template.getBytes("UTF-8");
      String sourceMD5 = WXFileUtils.md5(bts);
      String sourceBase64MD5 = WXFileUtils.base64Md5(bts);
      ArrayList<String> sourceMD5List = new ArrayList<>();
      ArrayList<String> sourceBase64MD5List = new ArrayList<>();
      sourceMD5List.add(sourceMD5);
      sourceBase64MD5List.add(sourceBase64MD5);
      responseHeaders.put("templateSourceMD5", sourceMD5List);
      responseHeaders.put(SOURCE_TEMPLATE_BASE64_MD5, sourceBase64MD5List);
      return " template md5 " + sourceMD5 + " length " +   bts.length
              + " base64 md5 " + sourceBase64MD5
              + " response header " + JSONObject.toJSONString(responseHeaders);
    } catch (UnsupportedEncodingException e) {
      return "template md5 getBytes error";
    }

  }

  /**
   * check template header md5 match with header  content-md5
   * */
  public boolean isContentMd5Match(){
    if(responseHeaders == null){
      return true;
    }
    List<String> contentMD5s = responseHeaders.get("Content-Md5");
    if(contentMD5s == null){
      contentMD5s  = responseHeaders.get("content-md5");
    }
    if(contentMD5s == null || contentMD5s.size() <= 0){
      return true;
    }
    String md5 = contentMD5s.get(0);

    List<String> sourceBase64Md5 = responseHeaders.get(SOURCE_TEMPLATE_BASE64_MD5);
    if(sourceBase64Md5 == null){
      getTemplateInfo();
      sourceBase64Md5 = responseHeaders.get(SOURCE_TEMPLATE_BASE64_MD5);
    }
    if(sourceBase64Md5 == null || sourceBase64Md5.size() == 0){
      return  true;
    }
    return  md5.equals(sourceBase64Md5.get(0));
  }

  public String getTemplate() {
    if(templateRef == null){
      return  null;
    }
    return templateRef.get();
  }

  public void setTemplate(String template) {
    this.templateRef = new WeakReference<String>(template);
  }

  public interface NestedInstanceInterceptor {
    void onCreateNestInstance(WXSDKInstance instance, NestedContainer container);
  }

  public void OnVSync() {
    boolean forceLayout = WXBridgeManager.getInstance().notifyLayout(getInstanceId());
    if(forceLayout) {
      WXBridgeManager.getInstance().post(new Runnable() {
        @Override
        public void run() {
          WXBridgeManager.getInstance().forceLayout(getInstanceId());
        }
      });
    }
  }

  public void addContentBoxMeasurement(long renderObjectPtr, ContentBoxMeasurement contentBoxMeasurement) {
    mContentBoxMeasurements.put(renderObjectPtr, contentBoxMeasurement);
  }

  public ContentBoxMeasurement getContentBoxMeasurement(long renderObjectPtr) {
    return mContentBoxMeasurements.get(renderObjectPtr);
  }
}
