import Foundation
import ContentsquareSDK
import HeapSwiftCore
import React

@objc(RNHeapModule)
public class RNHeapModule: NSObject {

    var bridgeSupport: _HeapBridgeSupport
    @objc public weak var delegate: RNHeapModuleDelegate?

    @objc
    public convenience override init() {
        self.init(HeapBridgeSupport())
    }
    
    init(_ heapBridgeSupport: _HeapBridgeSupport) {
        self.bridgeSupport = heapBridgeSupport
        super.init()
        bridgeSupport.delegate = self
    }

    @objc(handleInvocation:arguments:resolver:rejecter:)
    public func handleInvocation(method: String, arguments: [String: Any], resolve: RCTPromiseResolveBlock, reject: RCTPromiseRejectBlock) {

        do {
            let result = try bridgeSupport.handleInvocation(method: method, arguments: arguments)
            if let result = result as? String {
                // This is a simple case, we don't need to go through the JSON encoder.
                resolve(result)
            } else if let result = result {
                // We need to convert from a Swift type to Foundation types for pageview payloads
                // to convert into JavaScript objects.
                let data = try result.toJSONData()
                let payload = try JSONSerialization.jsonObject(with: data, options: .fragmentsAllowed)
                resolve(payload)
            } else {
                resolve(nil)
            }
        } catch InvocationError.unknownMethod {
            reject("NOT_IMPLEMENTED", "The method \(method) is not implemented in the Swift runtime.", nil)
        } catch InvocationError.invalidParameters {
            reject("BAD_ARGS", "Invalid arguments sent to \(method) in the Swift runtime. See logs for details.", nil)
        } catch {
            reject("UNKNOWN", "An unknown error occurred while calling \(method) in the Swift runtime. See logs for details.", nil)
        }
    }

    @objc(handleResult:data:error:)
    public func handleResult(callbackId: String, data: Any?, error: String?) {
        bridgeSupport.handleResult(callbackId: callbackId, data: data, error: error)
    }
}

extension RNHeapModule: HeapSwiftCore.HeapBridgeSupportDelegate {
    public func sendInvocation(_ invocation: HeapSwiftCore.HeapBridgeSupport.Invocation) {
        do {
            // Convert the encodable payload into JSON primitives.
            let data = try JSONEncoder().encode(invocation)
            let payload = try JSONSerialization.jsonObject(with: data)
            delegate?.emitEvent("Invocation", data: payload as? [AnyHashable : Any])
        } catch {
            // TODO: Add method for rejecting a notice.
        }
    }
}
