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

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

import android.net.Uri;
import com.alibaba.fastjson.JSONException;
import com.alibaba.fastjson.JSONObject;
import com.taobao.weex.WXEnvironment;
import com.taobao.weex.WXSDKManager;
import com.taobao.weex.adapter.IWXHttpAdapter;
import com.taobao.weex.adapter.URIAdapter;
import com.taobao.weex.annotation.JSMethod;
import com.taobao.weex.bridge.JSCallback;
import com.taobao.weex.bridge.WXBridgeManager;
import com.taobao.weex.common.WXModule;
import com.taobao.weex.common.WXRequest;
import com.taobao.weex.common.WXResponse;
import com.taobao.weex.utils.WXLogUtils;
import java.io.UnsupportedEncodingException;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

public class WXStreamModule extends WXModule {

  public static final String STATUS_TEXT = "statusText";
  public static final String STATUS = "status";
  final IWXHttpAdapter mAdapter;
  static final Pattern CHARSET_PATTERN = Pattern.compile("charset=([a-z0-9-]+)");

  public WXStreamModule(){
    this(null);
  }
  public WXStreamModule(IWXHttpAdapter adapter){
    mAdapter = adapter;
  }

  /**
   * send HTTP request
   *
   * @param params   {method:POST/GET/PUT/DELETE/HEAD/PATCH,url:http://xxx,header:{key:value},
   *                 body:{key:value}}
   * @param callback formate：handler(err, response)
   */
  @Deprecated
  @JSMethod(uiThread = false)
  public void sendHttp(JSONObject paramsObj, final String callback) {

    String method = paramsObj.getString("method");
    String url = paramsObj.getString("url");
    JSONObject headers = paramsObj.getJSONObject("header");
    String body = paramsObj.getString("body");
    int timeout = paramsObj.getIntValue("timeout");

    if (method != null) method = method.toUpperCase();
    Options.Builder builder = new Options.Builder()
            .setMethod(!"GET".equals(method)
                    &&!"POST".equals(method)
                    &&!"PUT".equals(method)
                    &&!"DELETE".equals(method)
                    &&!"HEAD".equals(method)
                    &&!"PATCH".equals(method)?"GET":method)
            .setUrl(url)
            .setBody(body)
            .setTimeout(timeout);

    extractHeaders(headers,builder);
    sendRequest(builder.createOptions(), new ResponseCallback() {
      @Override
      public void onResponse(WXResponse response, Map<String, String> headers) {
        if(callback != null && mWXSDKInstance != null)
          WXBridgeManager.getInstance().callback(mWXSDKInstance.getInstanceId(), callback,
                  (response == null || response.originalData == null) ? "{}" :
                          readAsString(response.originalData,
                                  headers!=null?getHeader(headers,"Content-Type"):""
                          ));
      }
    }, null, mWXSDKInstance.getInstanceId(), mWXSDKInstance.getBundleUrl());
  }

  /**
   *
   * @param optionsStr request options include:
   *  method: GET 、POST、PUT、DELETE、HEAD、PATCH
   *  headers：object，request header
   *  url:
   *  body: "Any body that you want to add to your request"
   *  type: json、text、jsonp（json）
   * @param callback finished callback,response object:
   *  status：status code
   *  ok：boolean is success，http status200～299
   *  statusText： statusText
   *  data:  option type is json，data is object，not data is string
   *  headers: headers
   *
   * @param progressCallback in progress callback,for download progress and request state,response object:
   *  readyState: number connection status 1 OPENED 2 HEADERS_RECEIVED 3 LOADING
   *  status：status code
   *  length：headers Content-Length
   *  statusText：statusText
   *  headers: headers
   */
  @JSMethod(uiThread = false)
  public void fetch(JSONObject optionsObj , final JSCallback callback, JSCallback progressCallback){
    fetch(optionsObj, callback, progressCallback, mWXSDKInstance.getInstanceId(), mWXSDKInstance.getBundleUrl());
  }

  public void fetch(JSONObject optionsObj , final JSCallback callback, JSCallback progressCallback, String instanceId, String bundleURL){
    boolean invaildOption = optionsObj==null || optionsObj.getString("url")==null;
    if(invaildOption){
      if(callback != null) {
        Map<String, Object> resp = new HashMap<>();
        resp.put("ok", false);
        resp.put(STATUS_TEXT, Status.ERR_INVALID_REQUEST);
        callback.invoke(resp);
      }
      return;
    }
    String method = optionsObj.getString("method");
    String url = optionsObj.getString("url");
    JSONObject headers = optionsObj.getJSONObject("headers");
    String body = optionsObj.getString("body");
    String type = optionsObj.getString("type");
    int timeout = optionsObj.getIntValue("timeout");

    if (method != null) method = method.toUpperCase();
    Options.Builder builder = new Options.Builder()
        .setMethod(!"GET".equals(method)
            &&!"POST".equals(method)
            &&!"PUT".equals(method)
            &&!"DELETE".equals(method)
            &&!"HEAD".equals(method)
            &&!"PATCH".equals(method)?"GET":method)
        .setUrl(url)
        .setBody(body)
        .setType(type)
        .setTimeout(timeout);

    extractHeaders(headers,builder);
    final Options options = builder.createOptions();
    sendRequest(options, new ResponseCallback() {
      @Override
      public void onResponse(WXResponse response, Map<String, String> headers) {
        if(callback != null) {
          Map<String, Object> resp = new HashMap<>();
          if(response == null|| "-1".equals(response.statusCode)){
            resp.put(STATUS,-1);
            resp.put(STATUS_TEXT,Status.ERR_CONNECT_FAILED);
          }else {
            int code = Integer.parseInt(response.statusCode);
            resp.put(STATUS, code);
            resp.put("ok", (code >= 200 && code <= 299));
            if (response.originalData == null) {
              resp.put("data", null);
            } else {
              String respData = readAsString(response.originalData,
                  headers != null ? getHeader(headers, "Content-Type") : ""
              );
              try {
                resp.put("data", parseData(respData, options.getType()));
              } catch (JSONException exception) {
                WXLogUtils.e("", exception);
                resp.put("ok", false);
                resp.put("data","{'err':'Data parse failed!'}");
              }
            }
            resp.put(STATUS_TEXT, Status.getStatusText(response.statusCode));
          }
          resp.put("headers", headers);
          callback.invoke(resp);
        }
      }
    }, progressCallback, instanceId, bundleURL);
  }

  Object parseData(String data, Options.Type type) throws JSONException{
    if( type == Options.Type.json){
      return JSONObject.parse(data);
    }else if( type == Options.Type.jsonp){
      if(data == null || data.isEmpty()) {
        return new JSONObject();
      }
      int b = data.indexOf("(")+1;
      int e = data.lastIndexOf(")");
      if(b ==0 || b >= e || e <= 0){
        return new JSONObject();
      }

      data = data.substring(b,e);
      return JSONObject.parse(data);
    }else {
      return data;
    }
  }

  static String getHeader(Map<String,String> headers,String key){
    if(headers == null||key == null){
      return null;
    }
    if(headers.containsKey(key)){
      return headers.get(key);
    }else{
      return headers.get(key.toLowerCase());
    }
  }



  static String readAsString(byte[] data,String cType){
    String charset = "utf-8";
    if(cType != null){
      Matcher matcher = CHARSET_PATTERN.matcher(cType.toLowerCase());
      if(matcher.find()){
        charset = matcher.group(1);
      }
    }
    try {
      return new String(data,charset);
    } catch (UnsupportedEncodingException e) {
      WXLogUtils.e("", e);
      return new String(data);
    }
  }


  private void extractHeaders(JSONObject headers, Options.Builder builder){
    //set user-agent
    String UA = WXHttpUtil.assembleUserAgent(WXEnvironment.getApplication(),WXEnvironment.getConfig());
    if(headers != null){
      for (String key : headers.keySet()) {
        if (key.equals(KEY_USER_AGENT)) {
          UA = headers.getString(key);
          continue;
        }
        builder.putHeader(key, headers.getString(key));
      }
    }
    builder.putHeader(KEY_USER_AGENT,UA);
  }


  private void sendRequest(Options options,ResponseCallback callback,JSCallback progressCallback,String instanceId, String bundleURL){
    WXRequest wxRequest = new WXRequest();
    wxRequest.method = options.getMethod();
    wxRequest.url = WXSDKManager.getInstance().getURIAdapter().rewrite(bundleURL, URIAdapter.REQUEST,Uri.parse(options.getUrl())).toString();
    wxRequest.body = options.getBody();
    wxRequest.timeoutMs = options.getTimeout();
    wxRequest.instanceId = instanceId;

    if(options.getHeaders()!=null) {
      if (wxRequest.paramMap == null) {
        wxRequest.paramMap = options.getHeaders();
      } else {
        wxRequest.paramMap.putAll(options.getHeaders());
      }
    }

    IWXHttpAdapter adapter = ( mAdapter==null) ? WXSDKManager.getInstance().getIWXHttpAdapter() : mAdapter;
    if (adapter != null) {
      adapter.sendRequest(wxRequest, new StreamHttpListener(callback,progressCallback));
    }else{
      WXLogUtils.e("WXStreamModule","No HttpAdapter found,request failed.");
    }
  }

  private interface ResponseCallback{
    void onResponse(WXResponse response, Map<String, String> headers);
  }

  private static class StreamHttpListener implements IWXHttpAdapter.OnHttpListener {
    private ResponseCallback mCallback;
    private JSCallback mProgressCallback;
    private Map<String,Object> mResponse = new HashMap<>();
    private Map<String,String> mRespHeaders;

    private StreamHttpListener(ResponseCallback callback,JSCallback progressCallback) {
      mCallback = callback;
      mProgressCallback = progressCallback;
    }


    @Override
    public void onHttpStart() {
      if(mProgressCallback !=null) {
        mResponse.put("readyState",1);//readyState: number 1 OPENED 2 HEADERS_RECEIVED 3 LOADING
        mResponse.put("length",0);
        mProgressCallback.invokeAndKeepAlive(new HashMap<>(mResponse));
      }
    }

    @Override
    public void onHttpUploadProgress(int uploadProgress) {

    }

    @Override
    public void onHeadersReceived(int statusCode,Map<String,List<String>> headers) {
      mResponse.put("readyState", 2);
      mResponse.put("status", statusCode);

      Map<String, String> simpleHeaders = new HashMap<>();
      if (headers != null) {
        Iterator<Map.Entry<String, List<String>>> it = headers.entrySet().iterator();
        while (it.hasNext()) {
          Map.Entry<String, List<String>> entry = it.next();
          if (entry.getValue().size() > 0) {
            simpleHeaders.put(entry.getKey() == null ? "_" : entry.getKey(), entry.getValue().get(0));
          }
        }
      }

      mResponse.put("headers", simpleHeaders);
      mRespHeaders = simpleHeaders;
      if (mProgressCallback != null) {
        mProgressCallback.invokeAndKeepAlive(new HashMap<>(mResponse));
      }
    }

    @Override
    public void onHttpResponseProgress(int loadedLength) {
      mResponse.put("length",loadedLength);
      if(mProgressCallback!=null){
        mProgressCallback.invokeAndKeepAlive(new HashMap<>(mResponse));
      }

    }

    @Override
    public void onHttpFinish(final WXResponse response) {
      //compatible with old sendhttp
      if(mCallback!=null){
        mCallback.onResponse(response, mRespHeaders);
      }

      if(WXEnvironment.isApkDebugable()){
        WXLogUtils.d("WXStreamModule",response!=null && response.originalData!=null?new String(response.originalData):"response data is NUll!");
      }
    }
  }

}
