package com.xw.aisdk;

import android.app.Activity;
import android.content.Intent;
import android.os.Environment;
import android.os.StatFs;
import android.text.TextUtils;
import android.util.Log;

import androidx.annotation.Nullable;

import com.facebook.react.bridge.ActivityEventListener;
import com.facebook.react.bridge.BaseActivityEventListener;
import com.facebook.react.bridge.Callback;
import com.facebook.react.bridge.JSApplicationIllegalArgumentException;
import com.facebook.react.bridge.Promise;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;
import com.facebook.react.modules.core.DeviceEventManagerModule;
import com.google.gson.Gson;
import com.google.gson.TypeAdapter;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter;
import com.xuanwu.camera.EnumCameraMode;
import com.xuanwu.camera.EnumDataRetainedMode;
import com.xuanwu.camera.EnumVideoQuality;
import com.xuanwu.camera.XWCamera;
import com.xuanwu.camera.XWCameraResponse;
import com.xuanwu.enginesdk.AIDef;
import com.xuanwu.enginesdk.common.EngineCallback;
import com.xuanwu.enginesdk.manager.EngineManager;
import com.xuanwu.enginesdk.model.AIDetectionResult;
import com.xuanwu.enginesdk.model.BlurData;
import com.xuanwu.enginesdk.model.InitData;
import com.xuanwu.enginesdk.model.SceneInfos;
import com.xuanwu.enginesdk.model.SdkErrorEnum;
import com.xuanwu.enginesdk.model.SkuData;
import com.xuanwu.enginesdk.utils.EngineContext;
import com.xuanwu.enginesdk.utils.EngineLog;
import com.xuanwu.enginesdk.manager.BaseManager;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import com.google.gson.GsonBuilder;

import java.io.File;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;


public class RNAisdkModule extends ReactContextBaseJavaModule {
    public static final String REACT_NATIVE_CLASSNAME = "NativeManager";
    private ReactApplicationContext mContext;
    public static final String EVENT_NAME = "nativeCallRn";
    public static final String TAG = "RNAisdkModule";
    public static final int REQUEST_CODE = 101;
    private Promise mPromise;

    public RNAisdkModule(ReactApplicationContext reactContext) {
        super(reactContext);
        mContext = reactContext;
        reactContext.addActivityEventListener(mActivityEventListener);
    }

    @Override
    public String getName() {
        //返回的这个名字是必须的，在rn代码中需要这个名字来调用该类的方法。
        return REACT_NATIVE_CLASSNAME;
    }

    private final ActivityEventListener mActivityEventListener = new BaseActivityEventListener() {

        @Override
        public void onActivityResult(Activity activity, int requestCode, int resultCode, Intent intent) {
            if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) {
                Gson gson = new GsonBuilder()
                        .registerTypeAdapter(XWCameraResponse.Data.class, new SensorTypeAdapter())
                        .create();
                XWCameraResponse response = (XWCameraResponse) intent.getSerializableExtra("data");
                       String result = gson.toJson(response);
            try {
                JSONObject jsonObject = new JSONObject(result);
                JSONArray jsonArray = jsonObject.optJSONArray("data");
                for (int i = 0; i < jsonArray.length(); i++) {
                    JSONObject dataObject = (JSONObject) jsonArray.get(i);

                    if (dataObject.optString("cameraMode").equals("video")) {
                        dataObject.remove("isRemake");
                    }
                }
                result = jsonObject.toString();
            } catch (JSONException e) {
                e.printStackTrace();
            }
           
                mPromise.resolve(result);
                mPromise = null;
            }
        }
    };

    public class SensorTypeAdapter extends TypeAdapter<XWCameraResponse.Data> {

        @Override
        public void write(JsonWriter out, XWCameraResponse.Data value) throws IOException {
            out.beginObject();
            //按自定义顺序输出字段信息
            out.name("id").value(value.getId());
            out.name("path").value(value.getPath());
            out.name("cameraType").value(value.getCameraType());
            out.name("cameraMode").value(value.getCameraMode());
            out.name("mosaicPictureUrl").value(value.getMosaicPictureUrl());
            out.name("isRemake").value(value.isRemake());
            out.endObject();
        }

        @Override
        public XWCameraResponse.Data read(JsonReader in) throws IOException {
            return null;
        }
    }

    private void sendEventToRn(String eventName, String data) {
        if (getReactApplicationContext() == null) {
            return;
        }
     
        getReactApplicationContext().getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class)
                .emit(eventName, data);
    }

    @ReactMethod
    public void callNative(String functionName, String data, Promise promise) {
        String path = "";
        switch (functionName) {
            case "Init":


                AIDef.Config.Builder builder = new AIDef.Config.Builder(mContext);
                try {
                    JSONObject jsonObject = new JSONObject(data);


                    if (!jsonObject.has("accessKey")) {
                        sendEventToRn("sendEventToRn", new Gson().toJson(new RnResponse(102, "缺少必须参数，缺少accessKey","")));
                        return;
                    }
                    if (!jsonObject.has("accountId")) {
                        sendEventToRn("sendEventToRn", new Gson().toJson(new RnResponse(102, "缺少必须参数，accountId","")));
                        return;
                    }
                    if (!jsonObject.has("account")) {
                        sendEventToRn("sendEventToRn", new Gson().toJson(new RnResponse(102, "缺少必须参数，account","")));
                        return;
                    }
                    String accessKey = jsonObject.optString("accessKey");
                    String accountId = jsonObject.optString("accountId");
                    String account = jsonObject.optString("account");


                    builder.accessKey(accessKey)
                            .accountId(accountId)
                            .account(account)
                            .isDebug(true);
                } catch (JSONException e) {
                    e.printStackTrace();
                }

                EngineManager.getInstance().initSDK(builder.build(), new EngineCallback<InitData>() {
                    @Override
                    public void onSuccess(InitData data) {
                        EngineLog.e(data.toString());
                        RnResponse response = new RnResponse(200, "成功");
                        response.setData(data);
                        sendEventToRn("sendEventToRn", new Gson().toJson(response));
                    }

                    @Override
                    public void onFailed(String code, String errorMsg) {
                        sendEventToRn("sendEventToRn", new Gson().toJson(new RnResponse(Integer.parseInt(code), "" + errorMsg,"")));
                    }
                });

                promise.resolve(null);
                break;
            case "Camera":
                try {

                    if (!BaseManager.checkInitState()) {
                     
                        promise.resolve(new Gson().toJson(new RnResponse<String>(999, "服务未初始化","")));
                        return;
                    }
                    long availableRom = getAvailableRom();
                    if (availableRom <= 0) {
                        promise.resolve(new Gson().toJson(new RnResponse<String>(999, "手机内存已满，请清理内存后再进行拍照或录制视频","")));
                        return;
                    }
                       EngineLog.e("CameraData"+data);
                    JSONObject jsonObject = new JSONObject(data);

                    String dataRetainedMode = jsonObject.optString("dataRetainedMode");
                    if (!TextUtils.isEmpty(dataRetainedMode) && !dataRetainedMode.equals("clear") && !dataRetainedMode.equals("retain")) {
                        promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，dataRetainedMode值有误","")));
                        return;
                    }

                    JSONArray cameraModeArray = jsonObject.optJSONArray("cameraMode");
                    if (cameraModeArray == null) {
                        promise.resolve(new Gson().toJson(new RnResponse<String>(102, "缺少必须参数，缺少cameraMode参数","")));
                        return;
                    }
                    for (int i = 0; i < cameraModeArray.length(); i++) {
                        JSONObject modeObject = cameraModeArray.optJSONObject(i);
                        String mode = modeObject.optString("mode");




                        String type = modeObject.optString("type");
                        int quality = modeObject.optInt("quality");
                        String videoQuality = modeObject.optString("videoQuality");
                        int recTime = modeObject.optInt("recTime");
                        int quantity = modeObject.optInt("quantity");
                        boolean showPreview = modeObject.optBoolean("showPreview");
                        String flashMode = modeObject.optString("flashMode");
            
                        if (!modeObject.has("mode") || TextUtils.isEmpty(mode)) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(102, "缺少必须参数，缺少mode参数","")));
                            return;
                        }
                 if (!mode.equals(EnumCameraMode.CONTINUOUS.getName()) && !mode.equals(EnumCameraMode.SINGLE.getName()) && ! mode.equals(EnumCameraMode.VIDEO.getName()) && ! mode.equals(EnumCameraMode.PANORAMA.getName()) && ! mode.equals(EnumCameraMode.PANORAMA_PLUS.getName())) {
                      promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，mode值有误","")));
                      return;

                }
                        if (mode.equals(EnumCameraMode.SINGLE.getName()) && "retain".equals(dataRetainedMode)) {
                            if (cameraModeArray.length() > 1 ) {
                                promise.resolve(new Gson().toJson(new RnResponse<String>(103, "混合模式保留数据不允许使用单拍模式","")));
                                return;
                            }

                        }

                        if (!TextUtils.isEmpty(type) && !type.equals("front") && !type.equals("back")) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，type值有误","")));
                            return;
                        }

                        if (!TextUtils.isEmpty(flashMode) && !flashMode.equals("on") && !flashMode.equals("off") && !flashMode.equals("auto")) {
                          
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，flashMode值有误","")));
                            return;
                        }

                        if (jsonObject.has("quality") && quality <= 0 || quality > 100) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，quality值有误","")));
                            return;
                        }

                        if (!TextUtils.isEmpty(videoQuality) && !videoQuality.equals("480") && !videoQuality.equals("720") && !videoQuality.equals("1080") && !videoQuality.equals("2160")) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，videoQuality值有误","")));
                            return;
                        }
                        if (jsonObject.has("recTime") && recTime <= 0) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，recTime值有误","")));
                            return;
                        }
                        if (jsonObject.has("quantity") && quantity <= 0) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数异常，quantity值有误","")));
                            return;
                        }
                    }
                    XWCamera.from(getCurrentActivity()).setCameraParam(data).start(REQUEST_CODE);



                    mPromise = promise;
                } catch (Exception e) {
                    promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数解析异常","")));
                    e.printStackTrace();
                }


                break;

            case "isRemake":
                try {

                    if (!BaseManager.checkInitState()) {
                        promise.resolve(new Gson().toJson(new RnResponse<String>(999, "服务未初始化","")));
                        return;
                    }

                    JSONArray remakeArray = new JSONArray(data);
                    List<RnResponse.Data> list = new ArrayList<>();
                    for (int i = 0; i < remakeArray.length(); i++) {
                        JSONObject opt = (JSONObject) remakeArray.opt(i);
                        String filePath = opt.optString("filePath");
                        String id = opt.optString("id");

                        if (TextUtils.isEmpty(filePath)) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(102, "缺少必须参数，缺少filePath","")));
                            return;
                        }
                        if (TextUtils.isEmpty(id)) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(102, "缺少必须参数，缺少图片id","")));
                            return;
                        }

                        File file = new File(filePath);
                        if (!file.exists()) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, "图片路径不存在 [" + filePath + "]","")));
                            return;
                        }

                        AIDetectionResult result = EngineManager.getInstance().syncDetectFake(filePath);
                        if (!result.getStatus().equals("0")) {
                            promise.resolve(new Gson().toJson(new RnResponse<String>(999, result.getMsg())));
                            return;
                        }
                        RnResponse.Data tempData = new RnResponse.Data();
                        tempData.setId(id);
                        tempData.setRemake(result.getTaskLevel() == 1);
                        list.add(tempData);
                    }
                    RnResponse<List<RnResponse.Data>> response = new RnResponse<>(200, "成功");
                    response.setData(list);
                    promise.resolve(new Gson().toJson(response));

                } catch (Exception e) {
                    promise.resolve(new Gson().toJson(new RnResponse<String>(999, "参数解析异常","")));
                    e.printStackTrace();
                }


                break;

        }


    }


    public String getParam(String data, Promise promise) {
        String path = "";
        try {
            JSONObject jsonObject = new JSONObject(data);
            path = jsonObject.optString("path");
        } catch (Exception e) {

        }
        if (TextUtils.isEmpty(path)) {
            RnResponse response = new RnResponse(102, "缺少必须参数，缺少path参数");
            String json = new Gson().toJson(response);
            promise.resolve(json);
            return "";
        }
        return path;
    }


    @ReactMethod
    public void startActivityRN(String name, String params) {
        try {
            Activity activity = getCurrentActivity();
            if (activity != null) {
                Class toClass = Class.forName(name);
                Intent intent = new Intent(activity, toClass);
                intent.putExtra("params", params);
                activity.startActivity(intent);
            }
        } catch (Exception ex) {
            throw new JSApplicationIllegalArgumentException("不能打开Activity " + ex.getMessage());
        }
    }

    //后面该方法可以用Linking代替
    @ReactMethod
    public void getDataFromIntent(Callback success, Callback error) {
        try {
            Activity currentActivity = getCurrentActivity();
            String result = currentActivity.getIntent().getStringExtra("result");//会有对应数据放入
            if (!TextUtils.isEmpty(result)) {
                success.invoke(result);
            }
        } catch (Exception ex) {
            error.invoke(ex.getMessage());
        }
    }

    /**
     * Native调用RN
     *
     * @param msg
     */
    public void nativeCallRn(String msg) {
        mContext.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter.class).emit(EVENT_NAME, msg);
    }

    /**
     * Callback 方式
     * rn调用Native,并获取返回值
     *
     * @param data
     * @param callback
     */
    @ReactMethod
    public void rnCallNativeFromCallback(String data, Callback callback) {


    }

    /**
     * 向RN传递常量
     */
    @Nullable
    @Override
    public Map<String, Object> getConstants() {
        Map<String, Object> params = new HashMap<>();
        params.put("Constant", "我是Native常量，传递给RN");
        return params;
    }


    public long getAvailableRom() {
        File path = Environment.getDataDirectory();
        StatFs stat = new StatFs(path.getPath());
        long blockSize = stat.getBlockSizeLong();
        long availableBlocks = stat.getAvailableBlocksLong();
        return blockSize * availableBlocks / 1000000;//返回M
    }

}