package com.example.vnote_device_plugin;

import android.app.Application;
import android.util.Log;

import androidx.annotation.NonNull;

import com.example.vnote_device_plugin.utils.CommonUtils;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.reflect.Method;

import io.flutter.embedding.engine.plugins.FlutterPlugin;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MethodCall;
import io.flutter.plugin.common.MethodChannel;
import io.flutter.plugin.common.EventChannel;
import io.flutter.plugin.common.MethodChannel.MethodCallHandler;
import io.flutter.plugin.common.MethodChannel.Result;
import vinno.sportinspect.minterface.OnGlobalResultListener;
import vinno.sportinspect.sdk.VinnnoVnoteSdk;

/**
 * VnoteDevicePlugin
 */
public class VnoteDevicePlugin implements FlutterPlugin, MethodCallHandler {
    private static final String TAG = VnoteDevicePlugin.class.getSimpleName();
    /// The MethodChannel that will the communication between Flutter and native Android
    ///
    /// This local reference serves to register the plugin with the Flutter Engine and unregister it
    /// when the Flutter Engine is detached from the Activity
    private MethodChannel channel;
    private EventChannel eventChannel;
    private EventChannel.EventSink eventSink;
    private boolean hasInit = false;

    @Override
    public void onAttachedToEngine(@NonNull FlutterPluginBinding flutterPluginBinding) {
        final BinaryMessenger messenger = flutterPluginBinding.getBinaryMessenger();
        channel = new MethodChannel(messenger, "vnote_device_plugin");
        channel.setMethodCallHandler(this);
        eventChannel = new EventChannel(messenger, "vnote_device_plugin_event");

        final VnoteDevicePlugin that = this;
        eventChannel.setStreamHandler(new EventChannel.StreamHandler() {
            @Override
            public void onListen(Object arguments, EventChannel.EventSink eventSink) {
                Log.i(TAG, "OnListen EventSink!");
                that.eventSink = eventSink;
            }

            @Override
            public void onCancel(Object arguments) {
                that.eventSink = null;
            }
        });
    }

    @Override
    public void onMethodCall(@NonNull MethodCall call, @NonNull Result result) {
        handleMethodCall(call, result);
        // TODO: 默认开启了TreeShaking，无法使用反射
//        try {
//            // 反射查找
//            Method method = VnoteDevicePlugin.class.getDeclaredMethod(call.method, MethodCall.class, MethodChannel.Result.class);
//            method.invoke(this, call, result);
//        } catch (NoSuchMethodException e) {
//            // todo: log
//            result.notImplemented();
//        } catch (IllegalAccessException e) {
//            // todo: log
//            result.notImplemented();
//        } catch (Exception e) {
//            // todo: log
//            result.notImplemented();
//        }
    }

    private void handleMethodCall(MethodCall call, Result result) {
        try {
            switch (call.method) {
                case "getPlatformVersion":
                    getPlatformVersion(call, result);
                    break;
                case "init":
                    init(call, result);
                    break;
                case "setLogEnable":
                    setLogEnable(call, result);
                    break;
                case "callAction":
                    callAction(call, result);
                    break;
                default:
                    Log.w(TAG, String.format("Method - %s not implemented.", call.method));
                    result.notImplemented();
                    break;
            }
        } catch (Exception e) {
            Log.e(TAG, String.format("Handle method - %s error: %s.", call.method, e));
            result.notImplemented();
        }
    }

    private void getPlatformVersion(MethodCall call, Result result) {
        result.success("Android " + android.os.Build.VERSION.RELEASE);
    }

    private void init(MethodCall call, Result result) {
        final Boolean isDebug = CommonUtils.getParam(call, result, "isDebug");
        final Application application = CommonUtils.getCurApplication();
        //初始化SDK
        VinnnoVnoteSdk.getInstance().init(application, isDebug);
        //注册全局监听
        VinnnoVnoteSdk.getInstance().setOnGlobalResultListener(new OnGlobalResultListener() {
            @Override
            public void onResult(JSONObject jsonObject) {
                final String jsonText = jsonObject.toString();
                Log.d(TAG, jsonText);
                eventSink.success(jsonText);
            }
        });
        hasInit = true;
        Log.i(TAG, "SDK init done.");
        result.success(null);
    }

    private void setLogEnable(MethodCall call, Result result) {
        final Boolean enable = CommonUtils.getParam(call, result, "enable");
        final Application application = CommonUtils.getCurApplication();
        VinnnoVnoteSdk.getInstance().setLogEnable(application, enable);
        Log.i(TAG, "Set log enable to " + enable);
        result.success(null);
    }

    private void callAction(MethodCall call, Result result) throws JSONException {
        try {
            final String jsonText = CommonUtils.getParam(call, result, "request");
            final JSONObject jsonObject = new JSONObject(jsonText);
            VinnnoVnoteSdk.getInstance().request(jsonObject);
        } catch (Exception e) {
            Log.e(TAG, String.format("Call action error: %s.", e));
        }
        result.success(null);
    }

    @Override
    public void onDetachedFromEngine(@NonNull FlutterPluginBinding binding) {
        if (hasInit) {
            VinnnoVnoteSdk.getInstance().destroyAll();
            hasInit = false;
            Log.i(TAG, "SDK disposed!");
        }
        channel.setMethodCallHandler(null);
    }
}
