/**
 * 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.net.Uri;
import android.text.TextUtils;

import com.taobao.weex.adapter.IWXHttpAdapter;
import com.taobao.weex.adapter.IWXUserTrackAdapter;
import com.taobao.weex.common.WXErrorCode;
import com.taobao.weex.common.WXPerformance;
import com.taobao.weex.common.WXRenderStrategy;
import com.taobao.weex.common.WXResponse;
import com.taobao.weex.performance.WXInstanceApm;
import com.taobao.weex.tracing.WXTracing;
import com.taobao.weex.utils.WXLogUtils;
import com.taobao.weex.utils.tools.LogDetail;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * load bundle js listener
 */
public 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 WXPerformance mWXPerformance;
    private WXInstanceApm mApmForInstance;
    private IWXUserTrackAdapter mUserTrackAdapter;
    public boolean isPreDownLoadMode = false;
    private boolean isInstanceReady =false;
    private boolean isResponseHasWait = false;
    private WXResponse mResponse;
    private LogDetail mLogDetail;

    private String mBundleUrl;

    public WXHttpListener(WXSDKInstance instance) {
        if(instance != null) {
            mLogDetail = instance.mTimeCalculator.createLogDetail("downloadBundleJS");
        }
        this.instance = instance;
        this.traceId = WXTracing.nextId();
        this.mWXPerformance = instance.getWXPerformance();
        this.mApmForInstance = instance.getApmForInstance();
        this.mUserTrackAdapter = WXSDKManager.getInstance().getIWXUserTrackAdapter();
        if (WXTracing.isAvailable()) {
            WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", instance.getInstanceId(), -1);
            event.iid = instance.getInstanceId();
            event.tname = "Network";
            event.ph = "B";
            event.traceId = traceId;
            event.submit();
        }
    }

    public WXHttpListener(WXSDKInstance instance, String bundleUrl) {
        this(instance);
        this.startRequestTime = System.currentTimeMillis();
        this.mBundleUrl = bundleUrl;
    }

    public WXHttpListener(WXSDKInstance instance, String pageName, Map<String, Object> options, String jsonInitData, WXRenderStrategy flag, long startRequestTime) {
        this(instance);
        this.pageName = pageName;
        this.options = options;
        this.jsonInitData = jsonInitData;
        this.flag = flag;
        this.startRequestTime = startRequestTime;
        this.mBundleUrl = instance.getBundleUrl();
    }

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

    protected WXSDKInstance getInstance() {
        return instance;
    }

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

    @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) {
        instance.getApmForInstance().extInfo.put(WXInstanceApm.VALUE_BUNDLE_LOAD_LENGTH,loadedLength);
    }

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

        if (WXTracing.isAvailable()) {
            WXTracing.TraceEvent event = WXTracing.newEvent("downloadBundleJS", instance.getInstanceId(), -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(null!= response && response.extendParams!=null){
            mApmForInstance.updateRecordInfo(response.extendParams);
            Object actualNetworkTime=response.extendParams.get("actualNetworkTime");
            mWXPerformance.actualNetworkTime=actualNetworkTime instanceof Long?(long)actualNetworkTime:0;

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

            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(WXPerformance.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(instance.getInstanceId());
                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(instance.getContext(), null, IWXUserTrackAdapter.JS_DOWNLOAD, performance, null);
                }
            }
        }

        if (isPreDownLoadMode){
            if (isInstanceReady){
                WXLogUtils.d("test->", "DownLoad didHttpFinish on http" );
                didHttpFinish(response);
            }else {
                WXLogUtils.d("test->", "DownLoad end before activity created" );
                mResponse = response;
                isResponseHasWait = true;
            }
        }else {
            didHttpFinish(response);
        }

    }

    public void onInstanceReady(){
        if (!isPreDownLoadMode){
            return;
        }
        this.isInstanceReady = true;
        if (isResponseHasWait){
            WXLogUtils.d("test->", "preDownLoad didHttpFinish on ready" );
            this.didHttpFinish(mResponse);
        }

    }

    private void didHttpFinish(WXResponse response){
        String wxErrorCode = WXInstanceApm.VALUE_ERROR_CODE_DEFAULT;
        if (response!=null && response.originalData!=null && TextUtils.equals("200", response.statusCode)) {
            mApmForInstance.onStage(WXInstanceApm.KEY_PAGE_STAGES_DOWN_BUNDLE_END);
            onSuccess(response);

            // 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");
            wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_BUNDLE_CONTENTTYPE_ERROR.getErrorCode();
            instance.onRenderError(wxErrorCode,
                    "|response.errorMsg==" + response.errorMsg +
                            "|instance bundleUrl = \n" + instance.getBundleUrl() +
                            "|instance requestUrl = \n" + Uri.decode(WXSDKInstance.requestUrl)
            );
            onFail(response);

            // 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");
            wxErrorCode =  WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode();
            instance.onRenderError(wxErrorCode ,
                    WXErrorCode.WX_DEGRAD_ERR_NETWORK_CHECK_CONTENT_LENGTH_FAILED.getErrorCode() +
                            "|response.errorMsg==" + response.errorMsg
            );
            onFail(response);
        }
        else {
            wxErrorCode = WXErrorCode.WX_DEGRAD_ERR_NETWORK_BUNDLE_DOWNLOAD_FAILED.getErrorCode();
            instance.onRenderError(wxErrorCode,
                    response.errorMsg);
            onFail(response);
        }
        if (!WXInstanceApm.VALUE_ERROR_CODE_DEFAULT.equals(wxErrorCode)){
            mApmForInstance.addProperty(WXInstanceApm.KEY_PROPERTIES_ERROR_CODE,wxErrorCode);
        }
    }

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

    public void onSuccess(WXResponse response) {
        if (flag==WXRenderStrategy.DATA_RENDER_BINARY){
            instance.render(pageName, response.originalData, options, jsonInitData);
        }else {
            String template = new String(response.originalData);
            instance.render(pageName, template, options, jsonInitData, flag);
        }
    }

    public void onFail(WXResponse response) {

    }
}


