//
//  CounterBadgePlugin.swift
//  Astro
//
//  Created by Liz Cross on 2015-07-13.
//  Copyright (c) 2015 Mobify Research & Development Inc. All rights reserved.
//

import Foundation
import UIKit

// UILabel with insets (e.g. paddings)
class BadgeLabel: UILabel {

    // Padding added around the text inside the label
    private let edgeInsets = UIEdgeInsets(top: 2.0, left: 6.0, bottom: 2.0, right: 6.0)

    override func textRect(forBounds bounds: CGRect, limitedToNumberOfLines numberOfLines: Int) -> CGRect {
        var rect = super.textRect(forBounds: bounds.inset(by: edgeInsets), limitedToNumberOfLines: numberOfLines)

        rect.origin.x -= edgeInsets.left
        rect.origin.y -= edgeInsets.top
        rect.size.width  += (edgeInsets.left + edgeInsets.right)
        rect.size.height += (edgeInsets.top + edgeInsets.bottom)

        return rect
    }

    override func drawText(in rect: CGRect) {
        super.drawText(in: rect.inset(by: edgeInsets))
    }
}

public class CounterBadgePlugin: Plugin, ViewPlugin {
    @objc public let viewController = UIViewController()

    private let imageView = UIImageView()
    private let labelView = BadgeLabel()

    private var imagePath: String = ""
    private var currentCount = 0

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

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

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

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

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

        initImage()
        initCounter()
    }

    private func initImage() {
        viewController.view.addSubview(imageView)
        positionImage()
    }

    private func initCounter() {
        viewController.view.addSubview(labelView)
        styleCounter()
        positionCounter()
    }

    private func styleCounter() {
        labelView.backgroundColor = UIColor.red
        labelView.textColor = UIColor.white
        labelView.textAlignment = .center
        labelView.font = labelView.font.withSize(12.0)
        labelView.layer.masksToBounds = true
    }

    private func positionCounter() {
        labelView.translatesAutoresizingMaskIntoConstraints = false

        let rightContraint = NSLayoutConstraint(item: labelView, attribute: .trailing, relatedBy: .equal, toItem: viewController.view, attribute: .trailing, multiplier: 1, constant: -4)
        let topContraint = NSLayoutConstraint(item: labelView, attribute: .top, relatedBy: .equal, toItem: viewController.view, attribute: .top, multiplier: 1, constant: 2)

        viewController.view.addConstraint(rightContraint)
        viewController.view.addConstraint(topContraint)
    }

    private func positionImage() {
        // Define image constraints
        imageView.translatesAutoresizingMaskIntoConstraints = false
        imageView.contentMode = .center

        let widthContraint = NSLayoutConstraint(item: viewController.view, attribute: .width, relatedBy: .equal, toItem: imageView, attribute: .width, multiplier: 1, constant: 44)
        let heightContraint = NSLayoutConstraint(item: viewController.view, attribute: .height, relatedBy: .equal, toItem: imageView, attribute: .height, multiplier: 1, constant: 44)
        let centerXContraint = NSLayoutConstraint(item: imageView, attribute: .centerX, relatedBy: .equal, toItem: viewController.view, attribute: .centerX, multiplier: 1, constant: 0)
        let centerYContraint = NSLayoutConstraint(item: imageView, attribute: .centerY, relatedBy: .equal, toItem: viewController.view, attribute: .centerY, multiplier: 1, constant: 0)

        viewController.view.addConstraint(widthContraint)
        viewController.view.addConstraint(heightContraint)
        viewController.view.addConstraint(centerXContraint)
        viewController.view.addConstraint(centerYContraint)

        // Cannot sizeToFit here because the general UIView class
        // does not have a default implementation for sizeToFit unless
        // you are using constraints
        viewController.view.frame = CGRect(x: 0, y: 0, width: 44.0, height: 44.0)
    }

    private func updateImage(_ respond: RPCMethodCallback) {
        if let image = AstroFileUtils.image(filePath: imagePath, respond: respond) {
            imageView.image = image
        }
    }

    private func updateCounter() {
        labelView.text = "\(currentCount)"
        labelView.alpha = (currentCount > 0) ? 1 : 0
        labelView.sizeToFit()
        labelView.layer.cornerRadius = labelView.frame.size.height/2
    }

    // @RpcMethod
    func setImagePath(_ path: String, respond: RPCMethodCallback) {
        imagePath = path
        updateImage(respond)
    }

    // @RpcMethod
    @objc func setCount(_ count: Int) {
        currentCount = count
        updateCounter()
    }

    // @RpcMethod
    @objc func setBackgroundColor(_ color: String) {
        if let backgroundColor = UIColor(hex: color) {
            labelView.backgroundColor = backgroundColor
        }
    }

    // @RpcMethod
    @objc func setTextColor(_ color: String) {
        if let textColor = UIColor(hex: color) {
            labelView.textColor = textColor
        }
    }
}
