/*
 * 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 org.apache.weex;

import static org.apache.weex.http.WXHttpUtil.KEY_USER_AGENT;

import android.app.Activity;
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.util.Log;
import android.view.Menu;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ScrollView;
import com.alibaba.fastjson.JSONObject;
import org.apache.weex.adapter.IDrawableLoader;
import org.apache.weex.adapter.IWXConfigAdapter;
import org.apache.weex.adapter.IWXHttpAdapter;
import org.apache.weex.adapter.IWXImgLoaderAdapter;
import org.apache.weex.adapter.IWXJscProcessManager;
import org.apache.weex.adapter.IWXUserTrackAdapter;
import org.apache.weex.adapter.URIAdapter;
import org.apache.weex.appfram.websocket.IWebSocketAdapter;
import org.apache.weex.bridge.EventResult;
import org.apache.weex.bridge.NativeInvokeHelper;
import org.apache.weex.bridge.SimpleJSCallback;
import org.apache.weex.bridge.WXBridgeManager;
import org.apache.weex.bridge.WXModuleManager;
import org.apache.weex.bridge.WXParams;
import org.apache.weex.common.Constants;
import org.apache.weex.common.Destroyable;
import org.apache.weex.common.OnWXScrollListener;
import org.apache.weex.common.RenderTypes;
import org.apache.weex.common.WXConfig;
import org.apache.weex.common.WXErrorCode;
import org.apache.weex.common.WXModule;
import org.apache.weex.common.WXPerformance;
import org.apache.weex.common.WXRefreshData;
import org.apache.weex.common.WXRenderStrategy;
import org.apache.weex.common.WXRequest;
import org.apache.weex.dom.WXEvent;
import org.apache.weex.http.WXHttpUtil;
import org.apache.weex.instance.InstanceOnFireEventInterceptor;
import org.apache.weex.jsEngine.JSContext;
import org.apache.weex.jsEngine.JSEngine;
import org.apache.weex.layout.ContentBoxMeasurement;
import org.apache.weex.performance.WXInstanceApm;
import org.apache.weex.performance.WXStateRecord;
import org.apache.weex.performance.WhiteScreenUtils;
import org.apache.weex.render.WXAbstractRenderContainer;
import org.apache.weex.tracing.WXTracing;
import org.apache.weex.ui.action.GraphicActionAddElement;
import org.apache.weex.ui.component.NestedContainer;
import org.apache.weex.ui.component.WXComponent;
import org.apache.weex.ui.component.WXEmbed;
import org.apache.weex.ui.flat.FlatGUIContext;
import org.apache.weex.ui.view.WXScrollView;
import org.apache.weex.utils.Trace;
import org.apache.weex.utils.WXDeviceUtils;
import org.apache.weex.utils.WXExceptionUtils;
import org.apache.weex.utils.WXFileUtils;
import org.apache.weex.utils.WXJsonUtils;
import org.apache.weex.utils.WXLogUtils;
import org.apache.weex.utils.WXReflectionUtils;
import org.apache.weex.utils.WXUtils;
import org.apache.weex.utils.WXViewUtils;
import org.apache.weex.utils.cache.RegisterCache;
import org.apache.weex.utils.tools.LogDetail;
import org.apache.weex.utils.tools.TimeCalculator;
import java.io.Serializable;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.concurrent.ConcurrentHashMap;
import org.apache.weex.bridge.WXBridgeManager.BundType;


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

  /**
   * Devtool protocol
   */
  public static String ACTION_DEBUG_INSTANCE_REFRESH = "DEBUG_INSTANCE_REFRESH";
  public static String ACTION_INSTANCE_RELOAD = "INSTANCE_RELOAD";

  //Performance
  public boolean mEnd = false;
  public boolean mHasCreateFinish = 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 WXAbstractRenderContainer 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 boolean hasException = false;
  private boolean isRenderSuccess = false;
  private boolean createInstanceHeartBeat = 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 boolean mUseScroller = false;
  private int mInstanceViewPortWidth = 750;
  private boolean enableFullScreenHeight = false;
  private WXInstanceApm mApmForInstance;
  private @NonNull
  FlatGUIContext mFlatGUIContext =new FlatGUIContext();

  private Map<String,String> mContainerInfo;

  public boolean isNewFsEnd = false;
  private List<JSONObject> componentsInfoExceedGPULimit  = new LinkedList<>();

  /**
   * bundle type
   */
  public BundType bundleType;
  public long mRenderStartNanos;
  public int mExecJSTraceId = WXTracing.nextId();

  private boolean isViewDisAppear = false;

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

  private boolean mDisableSkipFrameworkInit = false;

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

  private List<ActionBarHandler> mWXActionbarHandlers;

  private List<OnBackPressedHandler> mWXBackPressedHandlers;

  private List<OnActivityResultHandler> mWXOnActivityResultHandlers;

  private WXSDKInstance mParentInstance;

  private String mRenderType = RenderTypes.RENDER_TYPE_NATIVE;

  private boolean mPageDirty = true;
  private boolean mFixMultiThreadBug = false;

  public TimeCalculator mTimeCalculator;
  /**
   * Default Width And Viewport is 750,
   * when screen width change, we adjust viewport to adapter screen change
   * */
  private boolean mAutoAdjustDeviceWidth = WXEnvironment.AUTO_ADJUST_ENV_DEVICE_WIDTH;

  public  List<JSONObject> getComponentsExceedGPULimit(){return componentsInfoExceedGPULimit;}
  @RestrictTo(Scope.LIBRARY)
  public void setComponentsInfoExceedGPULimit(JSONObject component){
    if(component!= null && !component.isEmpty()){
      componentsInfoExceedGPULimit.add(component);
    }
  }

  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<>();

  private List<InstanceOnFireEventInterceptor> mInstanceOnFireEventInterceptorList;


  /**
   * network handler
   */
  public interface ImageNetworkHandler {
    public String fetchLocal(String url);
  }

  public interface StreamNetworkHandler {
    public String fetchLocal(String url);
  }

  public interface CustomFontNetworkHandler {
    public String fetchLocal(String url);
  }

  private ImageNetworkHandler mImageNetworkHandler;

  private StreamNetworkHandler mStreamNetworkHandler;

  private CustomFontNetworkHandler mCustomFontNetworkHandler;

  public ImageNetworkHandler getImageNetworkHandler() {
    return mImageNetworkHandler;
  }

  public void setImageNetworkHandler(ImageNetworkHandler imageNetworkHandler) {
    this.mImageNetworkHandler = imageNetworkHandler;
  }

  public StreamNetworkHandler getStreamNetworkHandler() {
    return mStreamNetworkHandler;
  }

  public void setStreamNetworkHandler(StreamNetworkHandler streamNetworkHandler) {
    this.mStreamNetworkHandler = streamNetworkHandler;
  }

  public CustomFontNetworkHandler getCustomFontNetworkHandler() {
    return mCustomFontNetworkHandler;
  }

  public void setCustomFontNetworkHandler(CustomFontNetworkHandler customFontNetworkHandler) {
    this.mCustomFontNetworkHandler = customFontNetworkHandler;
  }


  /**
   *  ActionBar Handler
   */

  public interface ActionBarHandler {
    boolean onSupportNavigateUp();
  }

  public interface OnBackPressedHandler {
    boolean onBackPressed();
  }

  public static abstract class OnActivityResultHandler {
    private String id;

    public OnActivityResultHandler(String id) {
      this.id = id;
    }

    public abstract boolean onActivityResult(int requestCode, int resultCode, Intent data, String id);

    public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
      return onActivityResult(requestCode, resultCode, data, id);
    }
  }

  /**
   * 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){
     setWXAbstractRenderContainer(a);
  }

  public void setWXAbstractRenderContainer(WXAbstractRenderContainer 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());
        }
      });
    }
  }

  private int mMaxDeepLayer;

  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;
  }

  @RestrictTo(Scope.LIBRARY)
  public void  setEnableFullScreenHeight(boolean fullScreenHeight){enableFullScreenHeight = fullScreenHeight;}

  @RestrictTo(Scope.LIBRARY)
  public boolean isFullScreenHeightEnabled(){return enableFullScreenHeight;}

  public boolean isUseScroller() {
    return mUseScroller;
  }

  public void setUseScroller(boolean use) {
    mUseScroller = use;
  }

  public void setInstanceViewPortWidth(int instanceViewPortWidth) {
    setInstanceViewPortWidth(instanceViewPortWidth,false);

  }
  public void setInstanceViewPortWidth(int instanceViewPortWidth,boolean fromMetaModule){
    this.mInstanceViewPortWidth = instanceViewPortWidth;
    this.mAutoAdjustDeviceWidth = false;
    if(!fromMetaModule){
      WXBridgeManager.getInstance().setViewPortWidth(getInstanceId(), mInstanceViewPortWidth);
    }
  }
  public void resetDeviceDisplayOfPage(){
    WXBridgeManager.getInstance().setDeviceDisplayOfPage(getInstanceId(), WXViewUtils.getScreenWidth(getContext()), WXViewUtils.getScreenHeight(getContext()));
  }
  public void setPageKeepRawCssStyles(){
    WXBridgeManager.getInstance().setPageArgument(getInstanceId(),"reserveCssStyles","true");
  }
  public void reloadPageLayout(){
    WXBridgeManager.getInstance().reloadPageLayout(getInstanceId());
  }

  public void setAutoAdjustDeviceWidth(boolean autoAdjustViewPort){
    this.mAutoAdjustDeviceWidth = autoAdjustViewPort;
  }

  public boolean isAutoAdjustDeviceWidth(){
    return mAutoAdjustDeviceWidth;
  }

  private void setDeviceDisplay(float deviceWith, float deviceHeight, float scale){
    WXBridgeManager.getInstance().setDeviceDisplay(getInstanceId(), deviceWith, deviceHeight, scale);
  }



  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 preInit
  public WXSDKInstance(){
    mInstanceId = WXSDKManager.getInstance().generateInstanceId();
    mWXPerformance = new WXPerformance(mInstanceId);
    mApmForInstance = new WXInstanceApm(mInstanceId);
    WXSDKManager.getInstance().getAllInstanceMap().put(mInstanceId,this);
    mTimeCalculator = new TimeCalculator(this);
    initFixMultiThreadFlag();
  }


  private void initFixMultiThreadFlag() {
    IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
    if (adapter != null) {
      String config = adapter.getConfig("android_weex_ext_config", "fixMultiThreadBug", "true");
      mFixMultiThreadBug = Boolean.parseBoolean(config);
    }
  }

  /**
   * 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 boolean isHasException() {
    return hasException;
  }

  public void setHasException(boolean hasException) {
    this.hasException = hasException;
  }

  public void createInstanceFuncHeartBeat() {
    WXLogUtils.d("createInstanceFuncHeartBeat: " + mInstanceId);
    this.createInstanceHeartBeat = true;
    getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_END_EXCUTE_BUNDLE);
  }

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

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

  public void init(Context context) {
    initFixMultiThreadFlag();
    RegisterCache.getInstance().idle(true);
    mContext = context;
    mContainerInfo = new HashMap<>(4);
    mNativeInvokeHelper = new NativeInvokeHelper(mInstanceId);

    if (null == mWXPerformance){
      mWXPerformance = new WXPerformance(mInstanceId);
    }
    if (null == mApmForInstance){
      mApmForInstance = new WXInstanceApm(mInstanceId);
    }

    mWXPerformance.WXSDKVersion = WXEnvironment.WXSDK_VERSION;
    mWXPerformance.JSLibInitTime = WXEnvironment.sJSLibInitTime;

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

    WXSDKManager.getInstance().getAllInstanceMap().put(mInstanceId,this);

    mContainerInfo.put(WXInstanceApm.KEY_PAGE_PROPERTIES_CONTAINER_NAME, context instanceof Activity
            ? context.getClass().getSimpleName()
            :"unKnowContainer"
    );
    mContainerInfo.put(WXInstanceApm.KEY_PAGE_PROPERTIES_INSTANCE_TYPE,"page");

    // WXBridgeManager.getInstance().checkJsEngineMultiThread();
    mDisableSkipFrameworkInit = isDisableSkipFrameworkInDataRender();

    if(mTimeCalculator == null) {
      mTimeCalculator = new TimeCalculator(this);
    }
  }

  /**
   * 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 && mScrollView instanceof WXScrollView) {
      ((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) {
  }

  public void setContainerInfo(String key,String val){
    mContainerInfo.put(key,val);
  }

  public Map<String, String> getContainerInfo() {
    return mContainerInfo;
  }

  /**
   * 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) {
    render(pageName, new Script(template), options, jsonInitData, flag);
  }

  public void render(String pageName, Script template, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag) {
    mWXPerformance.beforeInstanceRender(mInstanceId);

    if(WXEnvironment.isApkDebugable() && WXPerformance.DEFAULT.equals(pageName)){

      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);
  }

  /**
   * Render binary template asynchronously in DATA_RENDER_BINARY strategy.
   */
  public void render(String pageName, byte[] template, Map<String, Object> options, String jsonInitData) {
    render(pageName, new Script(template), options, jsonInitData, WXRenderStrategy.DATA_RENDER_BINARY);
  }

  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;
    }
    renderInternal(pageName, new Script(template), options, jsonInitData, flag);
  }

  private boolean isPreInit = false;
  public boolean isPreInitMode(){
    return isPreInit;
  }

  private boolean isPreDownLoad =false;
  public boolean isPreDownLoad(){
    return isPreDownLoad;
  }

  public void onInstanceReady(){
    WXLogUtils.d("test->","onInstanceReady");
    mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_CONTAINER_READY);
    if (!isPreInit && !isPreDownLoad){
      return;
    }
    mApmForInstance.onInstanceReady(isPreDownLoad);
    if (isPreDownLoad){
        mHttpListener.onInstanceReady();
    }
  }

  public void preInit(String pageName,
                      String script,
                      Map<String, Object> options,
                      String jsonInitData,
                      WXRenderStrategy flag){
    isPreInit = true;
    mRenderStrategy = flag;
    Map<String, Object> renderOptions = options;
    if (renderOptions == null) {
      renderOptions = new HashMap<>();
    }
    //mApmForInstance.doInit();
    mApmForInstance.isReady = false;
    WXSDKManager.getInstance().createInstance(this, new Script(script), renderOptions, jsonInitData);
  }

  public void preDownLoad(String url,
                          Map<String, Object> options,
                          String jsonInitData,
                          WXRenderStrategy flag){
    this.isPreDownLoad =true;
    mRenderStrategy = flag;
    mApmForInstance.isReady = false;
    renderByUrl(url,url,options,jsonInitData,flag);
  }


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

    LogDetail logDetail = mTimeCalculator.createLogDetail("renderInternal");
    mRenderStrategy = flag;

    //some case ,from render(template),but not render (url)
    if (!mApmForInstance.hasInit()){
      mApmForInstance.doInit();
    }
    mApmForInstance.setPageName(pageName);
    mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_RENDER_ORGIGIN);
    mApmForInstance.doDelayCollectData();

    mWXPerformance.pageName = (TextUtils.isEmpty(pageName) ? "defaultBundleUrl":pageName);
    if (TextUtils.isEmpty(mBundleUrl)) {
      mBundleUrl = mWXPerformance.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;
    }

    TimeCalculator timeCalculator = new TimeCalculator(this);

    mWXPerformance.JSTemplateSize = template.length() / 1024f;
    mApmForInstance.addStats(WXInstanceApm.KEY_PAGE_STATS_BUNDLE_SIZE,mWXPerformance.JSTemplateSize);
    mRenderStartTime = System.currentTimeMillis();
    WXSDKManager.getInstance().setCrashInfo(WXEnvironment.WEEX_CURRENT_KEY,pageName);
    if(mAutoAdjustDeviceWidth && WXDeviceUtils.isAutoResize(mContext)){
         if(WXEnvironment.AUTO_UPDATE_APPLICATION_SCREEN_SIZE) {
             WXViewUtils.updateApplicationScreen(mContext);
         }
         WXParams params = WXBridgeManager.getInstance().getInitParams();
         if(params != null && !TextUtils.equals(params.getDeviceWidth(), String.valueOf(WXViewUtils.getScreenWidth(mContext)))){
           params.setDeviceWidth(String.valueOf(WXViewUtils.getScreenWidth(mContext)));
           params.setDeviceHeight(String.valueOf(WXViewUtils.getScreenHeight(mContext)));
           float density = WXEnvironment.sApplication.getResources().getDisplayMetrics().density;
           WXEnvironment.addCustomOptions(WXConfig.scale, Float.toString(density));
           String statusBarHeight =  null;
           if(WXViewUtils.getStatusBarHeight(mContext) > 0 ){
             statusBarHeight = String.valueOf(WXViewUtils.getStatusBarHeight(mContext));
           }
           WXBridgeManager.getInstance().updateInitDeviceParams(params.getDeviceWidth(),
                                                                params.getDeviceHeight(),
                                                                Float.toString(density), statusBarHeight);
           setDeviceDisplay(WXViewUtils.getScreenWidth(mContext),
                            WXViewUtils.getScreenHeight(mContext),
                            WXViewUtils.getScreenDensity(mContext));
         }
    }
    logDetail.taskStart();
    if (isPreInitMode()){
      getApmForInstance().onStage(WXInstanceApm.KEY_PAGE_STAGES_LOAD_BUNDLE_START);
      WXBridgeManager.getInstance().loadJsBundleInPreInitMode(getInstanceId(),template.getContent());
    } else {
      WXSDKManager.getInstance().createInstance(this, template, renderOptions, jsonInitData);
    }
    logDetail.taskEnd();
    mRendered = true;

    final IWXJscProcessManager wxJscProcessManager = WXSDKManager.getInstance().getWXJscProcessManager();

    if(wxJscProcessManager != null && wxJscProcessManager.shouldReboot()) {
      WXSDKManager.getInstance().postOnUiThread(new Runnable() {
        @Override
        public void run() {
          checkWhiteScreen();
          if(isDestroy || hasException || isRenderSuccess) {
            return;
          }

          // there is no need to reboot js engine if render by eagle
          if(isDataRender()) {
            return;
          }

          View containerView = getContainerView();
          if(containerView instanceof ViewGroup) {
            if(0 == ((ViewGroup) containerView).getChildCount()) {
              if(wxJscProcessManager.withException(WXSDKInstance.this)) {
                onJSException(String.valueOf(WXErrorCode.WX_ERR_RELOAD_PAGE),"jsc reboot","jsc reboot");
              }
              if(!createInstanceHeartBeat) {
                  WXBridgeManager.getInstance().callReportCrashReloadPage(mInstanceId, null);
                  WXLogUtils.e("callReportCrashReloadPage with jsc reboot");
              }
            }
          }
        }
      }, wxJscProcessManager.rebootTimeout());
    }
  }


  private void checkWhiteScreen(){
    if (isDestroy ||!WhiteScreenUtils.doWhiteScreenCheck()){
      return;
    }

    boolean isWS = WhiteScreenUtils.isWhiteScreen(this);
    if (!isWS){
      return;
    }
    WXErrorCode errorCode = createInstanceHeartBeat?WXErrorCode.WX_ERROR_WHITE_SCREEN:WXErrorCode.WHITE_SCREEN_RESPONSE_TIMEOUT;
    if (WXBridgeManager.getInstance().isRebootExceedLimit()){
      errorCode = WXErrorCode.WHITE_SCREEN_REBOOT_EXCEED_LIMIT;
    }
    Map<String,String> args = new HashMap<>(1);
    String vieTreeMsg = WhiteScreenUtils.takeViewTreeSnapShot(this);
    args.put("viewTree",null == vieTreeMsg?"null viewTreeMsg":vieTreeMsg);
    args.put("weexCoreThreadStackTrace",WXBridgeManager.getInstance().getWeexCoreThreadStackTrace());

    for (Map.Entry<String,String> entry: WXStateRecord.getInstance().getStateInfo().entrySet()){
      args.put(entry.getKey(),entry.getValue());
    }
    WXExceptionUtils.commitCriticalExceptionRT(getInstanceId(),errorCode,"checkEmptyScreen",errorCode.getErrorMsg(),args);
  }


  public boolean skipFrameworkInit(){
    return isDataRender() && !mDisableSkipFrameworkInit;
  }

  private boolean isDataRender() {
    return getRenderStrategy() == WXRenderStrategy.DATA_RENDER_BINARY || getRenderStrategy() == WXRenderStrategy.DATA_RENDER;
  }

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


    LogDetail logDetail = mTimeCalculator.createLogDetail("renderByUrlInternal");
    logDetail.taskStart();
    ensureRenderArchor();
    pageName = wrapPageName(pageName, url);
    mBundleUrl = url;
    mRenderStrategy = flag;
    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);
    }

    getWXPerformance().pageName = pageName;

    mApmForInstance.doInit();
    mApmForInstance.setPageName(pageName);

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

    boolean is_wlasm = false;
    if (uri != null && uri.getPath()!=null) {
      if(uri.getPath().endsWith(".wlasm")){
        is_wlasm =  true;
      }
    }
    if (is_wlasm){
      flag = WXRenderStrategy.DATA_RENDER_BINARY;
    }

    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()));
    wxRequest.paramMap.put("isBundleRequest","true");
    mHttpListener = new WXHttpListener(this, pageName, renderOptions, jsonInitData, flag, System.currentTimeMillis());
    mHttpListener.isPreDownLoadMode = isPreDownLoad;
    mHttpListener.setSDKInstance(this);
    mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_START);
    adapter.sendRequest(wxRequest, (IWXHttpAdapter.OnHttpListener) mHttpListener);
    logDetail.taskEnd();
  }

  private WXHttpListener mHttpListener = null;

  /**
   * 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(ACTION_INSTANCE_RELOAD);
        intent.putExtra("url", mBundleUrl);
        mContext.sendBroadcast(intent);
      }
      // mRendered = false;
      //    destroy();
      // renderInternal(mPackage, mTemplate, mOptions, mJsonInitData, mFlag);
      // refreshInstance("{}");
    } else {
      IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
      if (adapter != null) {
        boolean degrade = Boolean.parseBoolean(adapter
                .getConfig("android_weex_ext_config",
                        "degrade_to_h5_if_not_reload",
                        "true"));
        WXLogUtils.e("degrade : " + degrade);
        if(degrade) {
          onJSException(String.valueOf(WXErrorCode.WX_ERR_RELOAD_PAGE.getErrorCode()),"Do not reloadPage", "Do not reloadPage degradeToH5");
          WXLogUtils.e("Do not reloadPage degradeToH5");
        }
      }
    }
  }

  /**
   * 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() {
    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{
        if (WXEnvironment.isApkDebugable()){
            WXLogUtils.w("Warning :Component tree has not build completely,onActivityCreate can not be call!");
        }
    }

    mGlobalEventReceiver=new WXGlobalEventReceiver(this);
    try {
      getContext().registerReceiver(mGlobalEventReceiver, new IntentFilter(WXGlobalEventReceiver.EVENT_ACTION));
    } catch (Throwable e) {
      // Huawei may throw a exception if register more than 500 BroadcastReceivers
      WXLogUtils.e(e.getMessage());
      mGlobalEventReceiver = null;
    }

  }

  @Override
  public void onActivityStart() {

    // module listen Activity onActivityCreate
    WXModuleManager.onActivityStart(getInstanceId());
    if(mRootComp != null) {
      mRootComp.onActivityStart();
    }else{
        if (WXEnvironment.isApkDebugable()) {
            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{
        if (WXEnvironment.isApkDebugable()) {
            WXLogUtils.w("Warning :Component tree has not build completely,onActivityStart can not be call!");

        }
    }
    return true;
  }

  @Override
  public void onActivityPause() {
    onViewDisappear();
    if(!isCommit){
      if(mUseScroller){
        mWXPerformance.useScroller=1;
      }
      mWXPerformance.maxDeepViewLayer=getMaxDeepLayer();
      mWXPerformance.wxDims = mwxDims;
      mWXPerformance.measureTimes = measureTimes;
      if (mUserTrackAdapter != null) {
        mUserTrackAdapter.commit(mContext, null, IWXUserTrackAdapter.LOAD, mWXPerformance, getUserTrackParams());
      }
      isCommit=true;
    }
    // module listen Activity onActivityPause
    WXModuleManager.onActivityPause(getInstanceId());
    if(mRootComp != null) {
      mRootComp.onActivityPause();
    }else{
        if (WXEnvironment.isApkDebugable()) {
            WXLogUtils.w("Warning :Component tree has not build completely,onActivityPause can not be call!");
        }
    }

    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());
      /**
       *  Fix NPE just like {@link #onActivityResume()}
       */
      if (null != mContext){
        mContext.sendBroadcast(intent);
      }else {
        try {
          WXEnvironment.getApplication().sendBroadcast(intent);
        } catch (Exception e){
          WXLogUtils.e("weex",e);
        }
      }
      this.mCurrentGround = true;
    }

    //component appear
    if((WXEnvironment.isApkDebugable() || WXEnvironment.isPerf()) && mApmForInstance != null){
        WXLogUtils.e("PerformanceData " + mApmForInstance.toPerfString());
    }
  }


  @Override
  public void onActivityResume() {

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

    if(mRootComp != null) {
      mRootComp.onActivityResume();
    }else{
        if (WXEnvironment.isApkDebugable()) {
            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{
        if (WXEnvironment.isApkDebugable()) {
            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{
        if (WXEnvironment.isApkDebugable()) {
            WXLogUtils.w("Warning :Component tree has not build completely, onActivityDestroy can not be call!");
        }
    }
    this.mTimeCalculator.println();
    destroy();
  }

  @Override
  public boolean onActivityBack() {

    WXModuleManager.onActivityBack(getInstanceId());

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

    return false;
  }

  public boolean onSupportNavigateUp() {
    if (mWXActionbarHandlers != null) {
      for (ActionBarHandler handler : mWXActionbarHandlers) {
        if (handler.onSupportNavigateUp()) {
          return true;
        }
      }
    }
    return false;
  }

  public boolean onBackPressed() {
    if(mWXBackPressedHandlers != null) {
      for (OnBackPressedHandler handler : mWXBackPressedHandlers) {
        if(handler.onBackPressed()) {
          return true;
        }
      }
    }

    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{
        if (WXEnvironment.isApkDebugable()) {
            WXLogUtils.w("Warning :Component tree has not build completely, onActivityResult can not be call!");
        }
    }


    if (mWXOnActivityResultHandlers != null && !mWXOnActivityResultHandlers.isEmpty()) {
      for (OnActivityResultHandler onActivityResultHandler : mWXOnActivityResultHandlers) {
        if (onActivityResultHandler.onActivityResult(requestCode, resultCode, data)) {
          break;
        }
      }
    }

  }


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

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

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

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

  public void onViewDisappear(){
    isViewDisAppear = false;
    mApmForInstance.onDisAppear();
    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 boolean isViewDisAppear(){
    return isViewDisAppear;
  }

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


  public void onCreateFinish() {
    if(mHasCreateFinish){
      return;
    }
    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() {
    if (WXEnvironment.isApkDebugable()){
      WXLogUtils.d("Instance onUpdateSuccess");
    }
  }


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

  public void onRenderSuccess(final int width, final int height) {
    isRenderSuccess = true;
    if (!isNewFsEnd){
      getApmForInstance().arriveNewFsRenderTime();
    }
    if (!getApmForInstance().stageMap.containsKey(WXInstanceApm.KEY_PAGE_STAGES_INTERACTION)){
      getApmForInstance().arriveInteraction(getRootComponent());
    }

    long time = System.currentTimeMillis() - mRenderStartTime;
    long[] renderFinishTime = WXBridgeManager.getInstance().getRenderFinishTime(getInstanceId());

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

    mWXPerformance.totalTime = time;
    if(mWXPerformance.screenRenderTime<0.001){
      mWXPerformance.screenRenderTime =  time;
    }

    if (mRenderListener != null && mContext != null) {
      mRenderListener.onRenderSuccess(WXSDKInstance.this, width, height);
      if (mUserTrackAdapter != null) {
        WXPerformance performance=new WXPerformance(mInstanceId);
        performance.errCode=WXErrorCode.WX_SUCCESS.getErrorCode();
        performance.args=getBundleUrl();
        mUserTrackAdapter.commit(mContext,null,IWXUserTrackAdapter.JS_BRIDGE,performance,getUserTrackParams());
      }
      if (WXEnvironment.isApkDebugable()){
        WXLogUtils.d(WXLogUtils.WEEX_PERF_TAG, mWXPerformance.toString());
      }
    }
    if(WXEnvironment.isPerf()){
      WXLogUtils.e("weex_perf",mWXPerformance.getPerfData());
    }
  }

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

  public void onChangeElement(WXComponent component, boolean isOutOfScreen) {

    if (isDestroy()  || null == mRenderContainer || mWXPerformance == null ){
      return;
    }
    if (null == component || component.isIgnoreInteraction){
        return;
    }

    if (mRenderContainer.hasConsumeEvent()) {
      return;
    }

    long lastElementChangeTime = System.currentTimeMillis();

    long lazyLoadTime;

    if (mHasCreateFinish){
      lazyLoadTime = lastElementChangeTime - mWXPerformance.renderTimeOrigin;
      if (lazyLoadTime > 8000) {
        //force record detail performance data
        return;
      }
    }

    if (component.mIsAddElementToTree) {
      getWXPerformance().localInteractionViewAddCount++;
      if (!isOutOfScreen)
        getWXPerformance().interactionViewAddLimitCount++;
      component.mIsAddElementToTree = false;
    }

    if (!isOutOfScreen) {
      mApmForInstance.arriveInteraction(component);
    }
  }

  public void onRenderError(final String errCode, final String msg) {
    WXStateRecord.getInstance().recordException(getInstanceId(),"onRenderError,"+errCode+","+msg);
    if (mRenderListener != null && mContext != null) {
      WXLogUtils.e("onRenderError "+errCode +","+msg);
      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) {
    WXStateRecord.getInstance().recordException(getInstanceId(),"onJSException,"+errCode+","+function+"|"+exception);
    hasException = true;
    if (mRenderListener != null && mContext != null) {
      WXLogUtils.e("onJSException "+errCode +","+exception);
      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 onOldFsRenderTimeLogic(){
      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();
            }
          }
        });
      }
      mApmForInstance.arriveFSRenderTime();
      mWXPerformance.fsRenderTime = System.currentTimeMillis();
      mWXPerformance.screenRenderTime = System.currentTimeMillis() - mRenderStartTime;
  }

  public WXSDKInstance getParentInstance() {
    return mParentInstance;
  }

  public void setParentInstance(WXSDKInstance mParentInstance) {
    this.mParentInstance = mParentInstance;
  }

  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(mParentInstance != null){
         mParentInstance = null;
      }
      mApmForInstance.onEnd();


      if(mRendered) {
        WXSDKManager.getInstance().destroyInstance(mInstanceId);
      }

      try {
        if (mGlobalEventReceiver != null) {
          getContext().unregisterReceiver(mGlobalEventReceiver);
          mGlobalEventReceiver = null;
        }
      }catch (IllegalArgumentException e){
        WXLogUtils.w(WXLogUtils.getStackTrace(e));
      }

      if (mRootComp != null) {
        mRootComp.destroy();
        mRootComp = null;
      }

      if(mRenderContainer != null){
        destroyView(mRenderContainer);
      }


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

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

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

      if(mWXOnActivityResultHandlers != null && !mWXOnActivityResultHandlers.isEmpty()) {
        mWXOnActivityResultHandlers.clear();
      }

      if(mWXBackPressedHandlers != null && !mWXBackPressedHandlers.isEmpty()) {
        mWXBackPressedHandlers.clear();
      }

      if(mWXActionbarHandlers != null && !mWXActionbarHandlers.isEmpty()) {
        mWXActionbarHandlers.clear();
      }

      getFlatUIContext().destroy();
      mFlatGUIContext = null;
      mInstanceOnFireEventInterceptorList = null;
      mWXScrollListeners = null;
      mWXActionbarHandlers = null;
      mWXBackPressedHandlers = 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();
        }
      });

      //when report error in @WXExceptionUtils
      // instance may had destroy and remove,
      // so we delay remove from allInstanceMap
      WXBridgeManager.getInstance().postDelay(new Runnable() {
        @Override
        public void run() {
          WXSDKManager.getInstance().getAllInstanceMap().remove(mInstanceId);
        }
      },1000);
    }
  }

  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.mDeepInComponentTree =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 getRenderContainerPaddingRight() {
    if(mRenderContainer != null) {
      return mRenderContainer.getPaddingRight();
    }
    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 synchronized void registerActionbarHandler(ActionBarHandler actionBarHandler) {
    if(actionBarHandler == null) {
      return;
    }
    if(mWXActionbarHandlers == null) {
      mWXActionbarHandlers = new ArrayList<>();
    }

    mWXActionbarHandlers.add(actionBarHandler);
  }

  public synchronized void unRegisterActionbarHandler(ActionBarHandler actionBarHandler) {
    if(mWXActionbarHandlers != null && actionBarHandler != null) {
      mWXActionbarHandlers.remove(actionBarHandler);
    }
  }

  public synchronized void unRegisterOnActivityResultHandler(OnActivityResultHandler onActivityResultHandler) {
    if(mWXOnActivityResultHandlers != null && onActivityResultHandler != null) {
      mWXOnActivityResultHandlers.remove(onActivityResultHandler);
    }
  }

  public synchronized void registerOnActivityResultHandler(OnActivityResultHandler onActivityResultHandler) {
    if(onActivityResultHandler == null) {
      return;
    }

    if(mWXOnActivityResultHandlers == null) {
      mWXOnActivityResultHandlers = new ArrayList<>();
    }
    mWXOnActivityResultHandlers.add(onActivityResultHandler);
  }


  public synchronized void registerBackPressedHandler(OnBackPressedHandler backPressedHandler) {
    if(backPressedHandler == null) {
      return;
    }

    if(mWXBackPressedHandlers == null) {
      mWXBackPressedHandlers = new ArrayList<>();
    }

    mWXBackPressedHandlers.add(backPressedHandler);
  }

  public synchronized void unRegisterBackPressedHandler(OnBackPressedHandler backPressedHandler) {
    if(mWXBackPressedHandlers != null && backPressedHandler != null) {
      mWXBackPressedHandlers.remove(backPressedHandler);
    }
  }

  static int sScreenHeight = -1;
  public void setSize(int width, int height) {
    if (width > 0 && height > 0 & !isDestroy && mRendered && mRenderContainer != null) {
        if (sScreenHeight < 0){
            sScreenHeight = WXViewUtils.getScreenHeight(getContext());
        }
        if (sScreenHeight>0){
            double screenRatio = (double)height/(double)sScreenHeight *100;
            if(screenRatio>100){
              screenRatio =100;
            }
            getApmForInstance().addStats(WXInstanceApm.KEY_PAGE_STATS_BODY_RATIO,screenRatio);
        }
      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) {
    onInterceptInstanceEvent(getInstanceId(), elementRef, type, data, domChanges);
    if (null != mWXPerformance && mWXPerformance.fsCallEventTotalNum<Integer.MAX_VALUE){
      mWXPerformance.fsCallEventTotalNum++;
    }
    mApmForInstance.updateFSDiffStats(WXInstanceApm.KEY_PAGE_STATS_FS_CALL_EVENT_NUM,1);
    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 WXInstanceApm getApmForInstance() {
    return mApmForInstance;
  }

  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 int getMaxDeepLayer() {
    return mMaxDeepLayer;
  }

  public void setMaxDeepLayer(int maxDeepLayer) {
    mMaxDeepLayer = maxDeepLayer;
    mApmForInstance.updateMaxStats(WXInstanceApm.KEY_PAGE_STATS_MAX_DEEP_VIEW,maxDeepLayer);
  }

  public void setMaxDomDeep(int maxDomDeep){
    mApmForInstance.updateMaxStats(WXInstanceApm.KEY_PAGE_STATS_MAX_DEEP_DOM,maxDomDeep);
    if (null == mWXPerformance){
      return;
    }
    if (mWXPerformance.maxDeepVDomLayer <= maxDomDeep){
      mWXPerformance.maxDeepVDomLayer = maxDomDeep;
    }
  }

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

  /**
   * return md5, and bytes length
   * */
  public String getTemplateInfo() {
    String template = getTemplate();
    if(template == null){
      return " template md5 null ,httpHeader:" + JSONObject.toJSONString(responseHeaders);
    }
    if(TextUtils.isEmpty(template)){
      return " template md5  length 0 ,httpHeader" + 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 (Exception 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() {
    if(mFixMultiThreadBug) {
      if(!mPageDirty) {
        return;
      }
      WXBridgeManager.getInstance().post(new Runnable() {
        @Override
        public void run() {
          boolean forceLayout = WXBridgeManager.getInstance().notifyLayout(getInstanceId());
          if(forceLayout) {
            WXBridgeManager.getInstance().forceLayout(getInstanceId());
          }
        }
      });
    } else  {
      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);
  }


  private void onInterceptInstanceEvent(String instanceId, String elementRef, String type, Map<String, Object> data, Map<String, Object> domChanges) {
    if(this.mInstanceOnFireEventInterceptorList == null){
      return;
    }
    for(InstanceOnFireEventInterceptor instanceOnFireEventInterceptor : this.mInstanceOnFireEventInterceptorList){
      instanceOnFireEventInterceptor.onInterceptFireEvent(instanceId, elementRef, type, data, domChanges);
    }
  }

  public List<InstanceOnFireEventInterceptor> getInstanceOnFireEventInterceptorList(){
    if(this.mInstanceOnFireEventInterceptorList == null){
      this.mInstanceOnFireEventInterceptorList = new ArrayList<>();
    }
    return mInstanceOnFireEventInterceptorList;
  }


  public void addInstanceOnFireEventInterceptor(InstanceOnFireEventInterceptor instanceOnFireEventInterceptor) {
    if(instanceOnFireEventInterceptor == null){
      return;
    }
    if(!getInstanceOnFireEventInterceptorList().contains(instanceOnFireEventInterceptor)){
      getInstanceOnFireEventInterceptorList().add(instanceOnFireEventInterceptor);
    }
  }

  public String getRenderType() {
    return mRenderType;
  }

  public void setRenderType(String renderType) {
    this.mRenderType = renderType;
  }

  private static boolean isDisableSkipFrameworkInDataRender() {
    IWXConfigAdapter adapter = WXSDKManager.getInstance().getWxConfigAdapter();
    if (adapter == null) {
      return false;
    }
    String result = adapter.getConfig("wxeagle", "disable_skip_framework_init", "false");
    return "true".equals(result);
  }

  public boolean isPageDirty() {
    return mPageDirty;
  }

  public void setPageDirty(boolean mPageDirty) {
    this.mPageDirty = mPageDirty;
  }
}
