//
//  AstroWorker.swift
//  Astro
//
//  Created by Jeremy Wiebe on 2015-04-28.
//  Copyright (c) 2015 Mobify Research & Development Inc. All rights reserved.
//

import Foundation
import UIKit

let WORKER_ADDRESS = "AstroWorker:0"
let ASTRO_USER_AGENT = "Astro App"

class AstroWorker: BaseMessageReceiver, Addressable, WebBridgeDelegate {
    @objc let appJSURL: URL
    let messageBus: MessageBus
    let webBridge: WebBridge
    @objc let address: MessageAddress = WORKER_ADDRESS
    @objc var isBooted = false

    var webBridgeOwner: Addressable {
        return self
    }

    init(appJSURL: URL, messageBus: MessageBus, webBridge: WebBridge) {
        self.appJSURL = appJSURL
        self.messageBus = messageBus
        self.webBridge = webBridge
        super.init()

        self.addRpcMethodShim("subscribeToEvents") { params, respond in
            ////////// This will be autogenerated at some point //////////
            if let address: String = MethodShimUtils.getArg(params, key: "address", respond: respond) {
                self.subscribeToEvents(from: address, respond: respond)
            }
            /////////////////////////////////////////////////////////////
        }

        self.addRpcMethodShim("logMessage") { params, respond in
            ////////// This will be autogenerated at some point //////////
            if let message: String = MethodShimUtils.getArg(params, key: "message", respond: respond) {
                self.logMessage(message, respond: respond)
            }
            /////////////////////////////////////////////////////////////
        }

        self.messageBus.register(self)
        self.webBridge.webBridgeDelegate = self
    }

    func receiveMessageFromBridge(_ bridgeMessage: BridgeMessage) {
        if let message = WebBridgeUtils.message(from: bridgeMessage, owner: self) {
            messageBus.send(message)
        }
    }

    override func receive(_ request: RPCRequest) {
        if request is JSRPCRequest {
            WebBridgeUtils.send(request, toBridge: webBridge)
            return
        }
        super.receive(request)
    }

    override func receive(_ response: RPCResponse) {
        WebBridgeUtils.send(response, toBridge: webBridge)
    }

    override func receive(_ message: EventMessage) {
        WebBridgeUtils.send(message, toBridge: webBridge)
    }

    /**
     Boots the worker.

     Calling this method causes the worker to begin executing `app.js`.

     *Note*: Multiple calls to this method are ignored.
    */
    @objc func boot() {
        if isBooted {
            AstroLog.logger(AstroLog.Application).error("WARN: AstroWorker is already booted.  Cannot boot again.")
            return
        }

        let appJs = appJSURL.absoluteString

        // The worker is always going to have an initial page loaded by cordova
        // The js is relative to the Cordova index.html (in 'www') and so the '../')
        webBridge.addScript(atURL: "../" + appJs)
        isBooted = true
    }

    // @RpcMethod
    func subscribeToEvents(from address: MessageAddress, respond: RPCMethodCallback) {
        messageBus.listen(on: "\(address):events", receiver: self)
    }

    // @RpcMethod
    func logMessage(_ message: String, respond: RPCMethodCallback) {
        AstroLog.logger(AstroLog.Worker).debug("[Worker] \(message)")
    }
}
