//
//  RNGizSDKManagerModule.swift
//  RNGizSDKManagerModule
//
//  Copyright © 2022 Gizwits. All rights reserved.
//

import Foundation
import React
import GizwitsiOSSDK

struct GetProductConfigParams: Decodable {
    var productKey:String
}
struct GizFeedbackParams: Decodable {
    var uploadLog:Bool
    var contact:String
    var content:String
}

@objc(RNGizSDKManagerModule)
class RNGizSDKManagerModule: RCTEventEmitter, GizSdkEventHandlerDelegate  {
    
    static var devices: Array<GizwitsiOSSDK.GizDevice> = []
    
    override func supportedEvents() -> [String]! {
        return ["DeviceDataListener", "DeviceListListener", "DeviceStateListener", "DeviceBindStateListener"]
    }

    override init() {
        super.init()
        GizSDKManager.sharedInstance.setDelegate(delegate: self)
    }
    
    func onDeviceListUpdate(devices: Array<GizwitsiOSSDK.GizDevice>) {
        DispatchQueue.main.async { [self] in
            var devicesDict: Array<Any> = []
            RNGizSDKManagerModule.devices = devices
            devices.forEach { d in
                let dev = GizRNCallbackManager.convertToDictionary(object: d)
                if (dev != nil) {
                    devicesDict.append(dev!)
                }
            }
            sendEvent(withName: "DeviceListListener", body: devicesDict)
        }
    }
    
    func onDeviceBindState(did: String, isBind: Bool) {
        let data = [
            "did": did,
            "isBind": isBind,
        ] as [String : Any]
        sendEvent(withName: "DeviceBindStateListener", body: data)
    }
    
    func onDeviceData(device: GizwitsiOSSDK.GizDevice, result: GizwitsiOSSDK.GizJSON, type: GizwitsiOSSDK.GizCapability) {
        let data = [
            "device": GizRNCallbackManager.convertToDictionary(object: device) ?? [:],
            "data": GizRNCallbackManager.convertToDictionary(object: result) ?? [:],
            "type": type.rawValue
        ] as [String : Any]
        sendEvent(withName: "DeviceDataListener", body: data)
    }
    
    func onDeviceState(device: GizwitsiOSSDK.GizDevice, state: GizwitsiOSSDK.GizWifiDeviceNetStatus, isLogin: Bool, type: GizwitsiOSSDK.GizCapability) {
        let data = [
            "device": GizRNCallbackManager.convertToDictionary(object: device) ?? [:],
            "state": state.rawValue,
            "type": type.rawValue,
            "isLogin": isLogin
        ] as [String : Any]
        sendEvent(withName: "DeviceStateListener", body: data)
    }
    @objc
    public func initSDK(_ options: NSDictionary, result: @escaping RCTResponseSenderBlock) {
        if let config = RNGizParamsChecker.check(options: options, result: result, paramsType: GizConfigStruct.self) {
            GizSDKManager.sharedInstance.initSDK(config: config)
            GizRNCallbackManager.callbackWithResult(callback: result, result: GizResult<Int?, GizAPIException?>(data: nil, success: true))
        }
    }
    
    @objc
    public func getProductDataPointConfig(_ options: NSDictionary, result: @escaping RCTResponseSenderBlock) {
        if let config = RNGizParamsChecker.check(options: options, result: result, paramsType: GetProductConfigParams.self) {
            Task {
                let configData = await GizSDKManager.sharedInstance.getProductDataPointConfig(productKey: config.productKey)
                
                GizRNCallbackManager.callbackWithResult(callback: result, result: GizResult<String?, GizAPIException?>(data: configData, success: true))
            }
            
        }
        
    }
    
    @objc
    public func getDevices(_ options: NSDictionary, result: @escaping RCTResponseSenderBlock) {
        Task {
            let data = await GizSDKManager.sharedInstance.getDevices()
            GizRNCallbackManager.callbackWithResult(callback: result, result: GizResult<Array<GizDevice>?, GizAPIException?>(data: data, success: true))

        }
    }

    @objc
    public func startBleScan(_ options: NSDictionary, result: @escaping RCTResponseSenderBlock) {
        GizSDKManager.sharedInstance.startBleScan()
        GizRNCallbackManager.callbackWithResult(callback: result, result: GizResult<Int?, GizAPIException?>(data: nil, success: true))
    }

    @objc
    public func stopBleScan(_ options: NSDictionary, result: @escaping RCTResponseSenderBlock) {
        GizSDKManager.sharedInstance.stopBleScan()
        GizRNCallbackManager.callbackWithResult(callback: result, result: GizResult<Int?, GizAPIException?>(data: nil, success: true))
    }

    @objc
    public func cleanCache(_ options: NSDictionary, result: @escaping RCTResponseSenderBlock) {
        GizSDKManager.sharedInstance.cleanCache()
        GizRNCallbackManager.callbackWithResult(callback: result, result: GizResult<Int?, GizAPIException?>(data: nil, success: true))
    }

    @objc
    public func feedback(_ options: NSDictionary, result: @escaping RCTResponseSenderBlock) {
        if let config = RNGizParamsChecker.check(options: options, result: result, paramsType: GizFeedbackParams.self) {
            Task {
                await GizSDKManager.sharedInstance.feedback(uploadLog: config.uploadLog, contact: config.contact, content: config.content)
                GizRNCallbackManager.callbackWithResult(callback: result, result: GizResult<Int?, GizAPIException?>(data: nil, success: true))
            }
            
        }
        
    }

    @objc
    override static func requiresMainQueueSetup() -> Bool {
        return true
    }
}
