//
//  Copyright (c) 2015 Mobify Research & Development Inc. All rights reserved.
//

import Foundation

struct ListItem: Equatable {
    let id: String
    let label: String

    init(id: String, label: String) {
        self.id = id
        self.label = label
    }
}

func ==(lhs: ListItem, rhs: ListItem) -> Bool {
    return (lhs.id == rhs.id && lhs.label == rhs.label)
}

public class ListSelectPlugin: Plugin {
    @objc var listSelectController: UIAlertController!
    @objc var title = ""
    var list: [ListItem] = []
    @objc var cancelable: Bool = true
    @objc var actionType = UIAlertAction.self

    private let AlertStyle = "AlertStyle"

    public required init(address: MessageAddress, messageBus: MessageBus, pluginResolver: PluginResolver, options: JSONObject?) {
        super.init(address: address, messageBus: messageBus, pluginResolver: pluginResolver, options: options)

        // Rpc Methods should be automated
        self.addRpcMethodShim("setTitle") { params, respond in
            if let title: String = MethodShimUtils.getArg(params, key: "title", respond: respond) {
                self.setTitle(title, respond: respond)
            }
        }

        self.addRpcMethodShim("setList") { params, respond in
            if let list: [JSONObject] = MethodShimUtils.getArg(params, key: "list", respond: respond) {
                self.setList(list, respond: respond)
            }
        }

        self.addRpcMethodShim("addItem") { params, respond in
            if let item: JSONObject = MethodShimUtils.getArg(params, key: "item", respond: respond) {
                self.addItem(item, respond: respond)
            }
        }

        self.addRpcMethodShim("setCancelable") { params, respond in
            if let cancelable: Bool = MethodShimUtils.getArg(params, key: "cancelable", respond: respond) {
                self.setCancelable(cancelable, respond: respond)
            }
        }

        self.addAsyncRpcMethodShim("show") { params, respond in
            if let options: JSONObject? = MethodShimUtils.getOptionalArg(params, key: "options", respond: respond) {
                self.show(options, respond: respond)
            }
        }
    }

    // @RpcMethod
    func setTitle(_ title: String, respond: RPCMethodCallback) {
        self.title = title
    }

    // @RpcMethod
    func setList(_ list: [JSONObject], respond: RPCMethodCallback) {
        self.list.removeAll()
        for item in list {
            guard let listItem = parseItem(item, respond: respond) else {
                return
            }
            self.list.append(listItem)
        }
    }

    // @RpcMethod
    func addItem(_ item: JSONObject, respond: RPCMethodCallback) {
        if let listItem = parseItem(item, respond: respond) {
            list.append(listItem)
        }
    }

    // @RpcMethod
    func setCancelable(_ cancelable: Bool, respond: RPCMethodCallback) {
        self.cancelable = cancelable
    }

    private func extractAlertOption(_ options: JSONObject?) -> UIAlertController.Style {
        let style = options?["style"] as? String ?? ""
        return style == AlertStyle ? .alert : .actionSheet
    }

    // @RpcMethod
    func show(_ options: JSONObject?, respond: @escaping RPCMethodCallback) {

        let alertStyle = extractAlertOption(options)
        listSelectController = UIAlertController(title: Localization.translate(title), message: nil, preferredStyle: alertStyle)

        if cancelable {
            let cancelAction = actionType.init(title: Localization.translate("list_cancel"), style: .cancel) {_ in
                respond(.result(self.buildResult(true)))
            }
            listSelectController.addAction(cancelAction)
        }

        for item in list {
            let itemAction = actionType.init(title: Localization.translate(item.label), style: .default) {_ in
                respond(.result(self.buildResult(false, selected: item.id)))
            }
            listSelectController.addAction(itemAction)
        }

        if let currentViewController = UIApplication.shared.currentViewController {
            currentViewController.present(listSelectController, animated: true) {
            }
        }
    }

    private func buildResult(_ cancelled: Bool, selected: String = "") -> JSONObject {
        let result: JSONObject = ["cancelled": cancelled, "selected": selected]
        return result
    }

    func parseItem(_ item: JSONObject, respond: RPCMethodCallback) -> ListItem? {
        if let id = item["id"] as? String {
            if let label = item["label"] as? String {
                return ListItem(id: id, label: label)
            }
        }
        respond(.error("Error parsing list item"))
        return nil
    }
}
